如何使用 MVVM 模式在 Xamarin Forms 中为 ZXingScannerView 添加自定义覆盖?

How do I add a Custom Overlay for ZXingScannerView in Xamarin Forms using the MVVM pattern?

我花了一些时间在 SO 上的其他地方获取示例,以使 Zxing Scanner 视图与 ViewModel 一起工作。我能够触发扫描事件,但视觉效果都消失了。我现在正在尝试在扫描仪视图周围添加自定义叠加层以再次添加视觉效果,但它们看起来有点疯狂。

我想要的外观是让整个屏幕显示相机视图,并将叠加视觉效果“叠加”在顶部。

类 下面:

ScanningView.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="RMAGo.Features.Scanning.ScanningView"             
             xmlns:viewModelBase="clr-namespace:RMAGo.Framework;assembly=RMAGo" 
             viewModelBase:ViewModelLocator.AutoWireViewModel="true"
             xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
             Title="Scanning">   
   

            <zxing:ZXingDefaultOverlay                                
                x:Name="scannerOverlay"                                                       
                BottomText="Place the red line over the barcode you'd like to scan.">
            
                <zxing:ZXingScannerView
                    VerticalOptions="FillAndExpand"
                    HorizontalOptions="FillAndExpand"                     
                    IsScanning="{Binding IsScanning}" 
                    IsAnalyzing="{Binding IsAnalyzing}"
                    Result="{Binding Result, Mode=TwoWay}" 
                    ScanResultCommand="{Binding ScanCommand}" />                       
            
            </zxing:ZXingDefaultOverlay> 
</ContentPage>

ScanningViewModel.cs

using RMAGo.Features.Common;
using RMAGo.Features.Navigation;
using RMAGo.Features.Settings;
using RMAGo.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using ZXing;
using ZXing.Mobile;
using ZXing.Net.Mobile.Forms;

namespace RMAGo.Features.Scanning
{
    public class ScanningViewModel : ViewModelBase
    {
        private readonly IRMAApiService _rmaApiService;
        private readonly ISettingsService _settingsService;
        private readonly IDialogService _dialogService;
        private readonly INavigationService _navigationService;

        private string barcode = string.Empty;
        public string Barcode
        {
            get
            {
                return barcode;
            }
            set
            {
                barcode = value;
            }
        }       

        private bool _isAnalyzing = true;
        public bool IsAnalyzing
        {
            get { return _isAnalyzing; }
            set
            {
                if (!Equals(_isAnalyzing, value))
                {
                    _isAnalyzing = value;
                }
            }
        }        

        private bool _isScanning = true;
        public bool IsScanning
        {
            get { return _isScanning; }
            set
            {
                if (!Equals(_isScanning, value))
                {
                    _isScanning = value;
                }
            }
        }       

        public Command ScanCommand
        {
            get
            {
                return new Command(() =>

                {
                    IsAnalyzing = false;
                    IsScanning = false;

                    Device.BeginInvokeOnMainThread(async () =>
                    {
                        Barcode = Result.Text;
                        await _dialogService.ShowAlertAsync("Scanned Item", Result.Text, "Ok");
                    });

                    IsAnalyzing = true;
                    IsScanning = true;
                });               
            }
        }
        public Result Result { get; set; }        
        public ScanningViewModel(IRMAApiService rmaApiService, ISettingsService settingsService, IDialogService dialogService, INavigationService navigationService)
        {
            _rmaApiService = rmaApiService;
            _settingsService = settingsService;
            _dialogService = dialogService;
            _navigationService = navigationService;

           
            PropertyChanged += ScanningViewModel_PropertyChanged;
        }

        private void ScanningViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {           
        }
    }
}

结果截图

更新:我找到了我的解决方案。我在 github 上看到这个示例文件,它作为子项直接将叠加层和扫描视图添加到网格:https://github.com/Redth/ZXing.Net.Mobile/blob/master/Samples/Forms/Core/CustomScanPage.cs

一旦我看到我几乎只是遵循相同的方法,但在 xaml 中。 (注意:我卡住了一段时间,因为我列出了 Overlay,然后是扫描仪视图。顺序很重要,因为我猜每个都被放置在另一个之上,所以 overlay 必须排在第二位才能成为最后一个写入的在上面)

ScanningView.xaml

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="RMAGo.Features.Scanning.ScanningView"             
             xmlns:viewModelBase="clr-namespace:RMAGo.Framework;assembly=RMAGo" 
             viewModelBase:ViewModelLocator.AutoWireViewModel="true"
             xmlns:zxing="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
             Title="Scanning">   
   


    <Grid VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
        <zxing:ZXingScannerView                                      
                    IsScanning="{Binding IsScanning}" 
                    IsAnalyzing="{Binding IsAnalyzing}"
                    Result="{Binding Result, Mode=TwoWay}" 
                    ScanResultCommand="{Binding ScanCommand}" />    
         <zxing:ZXingDefaultOverlay               
                x:Name="scannerOverlay"                                                       
                BottomText="Place the red line over the barcode you'd like to scan." />            

    </Grid>   
             
</ContentPage>