Xamarin Forms Android:ZXingScannerPage返回按钮跳转主页问题
问题解决:ZXingScannerPage未扫描返回时跳转HomePage失败
问题分析
你的代码通过SemaphoreSlim.WaitAsync()等待扫描结果触发信号量释放,但用户点击返回按钮关闭ZXingScannerPage时,OnScanResult不会触发,信号量始终无法释放,导致Scanner()方法一直阻塞,后续executeScanner()里判断controlScanner的逻辑根本无法执行,自然无法完成HomePage跳转。
解决方案
需要监听ZXingScannerPage的页面消失事件,当页面未完成扫描就被关闭时,手动释放信号量并标记扫描未完成,让后续流程继续执行。同时处理Android物理返回键的场景,确保返回操作能触发对应逻辑。
修改步骤
- 创建ZXingScannerPage后,添加
Disappearing事件监听,当页面消失且未触发扫描结果时,释放信号量并设置controlScanner = false。 - 可选:重写扫描页面的
OnBackButtonPressed方法,处理Android物理返回键的情况。
修改后的代码示例
public async void executeScanner() { try { await Scanner(); if (controlScanner == false) { await DisplayAlert("Error", "Please scan a QR. Try again.", "OK"); checkDoubleCalled = true; await Shell.Current.GoToAsync($"//{nameof(HomePage)}"); } else { takePhotos(); } } catch (Exception ex) { // 可添加异常日志记录 } } private async Task Scanner() { controlScanner = false; // 初始化扫描状态为未完成 var scannerPage = new ZXingScannerPage(); scannerPage.AutoFocus(); scannerPage.Title = "Escanear remito"; using (SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 1)) { // 扫描结果处理逻辑 scannerPage.OnScanResult += (result) => { scannerPage.IsScanning = false; string resultado = Convert.ToString(result); if (resultado.Contains("http") || resultado.Contains("https") || !resultado.Contains("\t")) { Device.BeginInvokeOnMainThread(async () => { await Navigation.PopAsync(); await this.DisplayAlert("QR not valid", "El QR is not valid", "OK"); controlScanner = false; semaphoreSlim.Release(); }); } else Device.BeginInvokeOnMainThread(async () => { try { await Application.Current.MainPage.Navigation.PopAsync(); subs = result.Text.Split('\t'); string cadena = $"var1N°: {subs[0]}\nvar2 N°: {subs[1]}\nvar3 N°: {subs[2]}"; num.Text = $"N° var12: {subs[1]}"; controlScanner = true; await this.DisplayAlert("Data QR", cadena, "OK"); } catch (Exception ex) { checkDoubleCalled = true; controlScanner = false; await DisplayAlert("Error", "QR not valid. Try again", "OK"); await Shell.Current.GoToAsync($"//{nameof(HomePage)}"); } semaphoreSlim.Release(); }); }; // 监听扫描页面消失事件 scannerPage.Disappearing += (s, e) => { // 信号量未释放说明是用户主动返回未扫描 if (semaphoreSlim.CurrentCount == 0) { controlScanner = false; semaphoreSlim.Release(); } }; // 处理Android物理返回键(增强兼容性) scannerPage.OnBackButtonPressed += () => { controlScanner = false; semaphoreSlim.Release(); return Task.FromResult(true); // 标记返回事件已处理 }; await Navigation.PushAsync(scannerPage); await semaphoreSlim.WaitAsync(); } }
关键说明
Disappearing事件监听确保用户手动关闭扫描页时,能释放信号量让Scanner()方法结束阻塞,回到executeScanner()执行跳转逻辑。- 重写
OnBackButtonPressed是为了适配Android物理返回键,避免出现返回后流程卡住的情况。 - 初始化
controlScanner = false,避免初始状态异常导致逻辑判断出错。
内容的提问来源于stack exchange,提问作者F205
相关产品推荐
相关产品推荐

