You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin Forms Android:ZXingScannerPage返回按钮跳转主页问题

问题解决:ZXingScannerPage未扫描返回时跳转HomePage失败

问题分析

你的代码通过SemaphoreSlim.WaitAsync()等待扫描结果触发信号量释放,但用户点击返回按钮关闭ZXingScannerPage时,OnScanResult不会触发,信号量始终无法释放,导致Scanner()方法一直阻塞,后续executeScanner()里判断controlScanner的逻辑根本无法执行,自然无法完成HomePage跳转。

解决方案

需要监听ZXingScannerPage的页面消失事件,当页面未完成扫描就被关闭时,手动释放信号量并标记扫描未完成,让后续流程继续执行。同时处理Android物理返回键的场景,确保返回操作能触发对应逻辑。

修改步骤

  1. 创建ZXingScannerPage后,添加Disappearing事件监听,当页面消失且未触发扫描结果时,释放信号量并设置controlScanner = false。
  2. 可选:重写扫描页面的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 05:50:48