Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have spent some time getting examples elsewhere on SO to get a Zxing Scanner view to work with a ViewModel. I am able to get the scan event to fire, but the visuals had all disappeared. I'm trying now to add a custom overlay around the scanner view to add the visuals again, but they look a little crazy.

The look i'm going for is to have the entire screen show the camera view with the overlay visuals "overlayed" over the top.

Classes below:

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)
        {           
        }
    }
}

Results Screenshot

like image 223
LogicaLInsanity Avatar asked May 17 '19 15:05

LogicaLInsanity


1 Answers

Update: I've found my solution. I saw this sample file on github that added the overlay and the scanning view to the grid directly as children: https://github.com/Redth/ZXing.Net.Mobile/blob/master/Samples/Forms/Core/CustomScanPage.cs

Once I saw that I pretty much just followed the same approach but in xaml. (Note: I got stuck for awhile because I was listing the Overlay and THEN the scanner view. The order matters, because I guess each one is being laid out on top of the other, so overlay must come second to be the last one written on top)

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>
like image 136
LogicaLInsanity Avatar answered Nov 17 '22 08:11

LogicaLInsanity