afriscic / BarcodeScanning.Native.Maui

Barcode scanning library for .NET MAUI
https://www.nuget.org/packages/BarcodeScanning.Native.Maui
MIT License
159 stars 31 forks source link

Camera Freezes When Navigating Back #82

Open SrNandu opened 1 month ago

SrNandu commented 1 month ago

I have a aplication that pushes into the navigation stack diferrent pages, wich more than one has a CameraView to scan Barcodes. The problem occurs when i navigate back to a page that has a CameraView, it freezes. This only happen when i push more than 1 page with a CameraView and they are next to each other in the stack. I suspect it has something to do with the fact that the page i navigate back to it is not re instantiated, it is re used and the CameraView has some problem with that. This is the code of the page.

<pages:BasePage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:pages="clr-namespace:CAPATAZ.Collector.UI.Pages"
             xmlns:converters="clr-namespace:CAPATAZ.Collector.UI.Business.Converters"
             xmlns:vm="clr-namespace:CAPATAZ.Collector.Business.ViewModels;assembly=CAPATAZ.Collector.Business"
             xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
             xmlns:scanner="clr-namespace:BarcodeScanning;assembly=BarcodeScanning.Native.Maui"
             xmlns:strings="clr-namespace:CAPATAZ.Collector.Model.Strings;assembly=CAPATAZ.Collector.Model"
             x:Class="CAPATAZ.Collector.UI.Pages.BaseScanPage"       
             x:DataType="vm:BaseScanViewModel">

    <AbsoluteLayout>

        <scanner:CameraView
            x:Name="BarcodeView"
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0,0,1,1"
            TapToFocusEnabled="True"
            BarcodeSymbologies="QRCode"
            VibrationOnDetected="True"
            PauseScanning="{Binding IsProcessing}">
        </scanner:CameraView>

        <Rectangle
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0,0,1,1"
            IsVisible="{Binding IsProcessing}" 
            Opacity="0.6"
            BackgroundColor="{StaticResource Black}"/>

        <ActivityIndicator 
            AbsoluteLayout.LayoutFlags="All"
            AbsoluteLayout.LayoutBounds="0.5,0.5"
            VerticalOptions="Center" 
            HorizontalOptions="Center"
            IsVisible="{Binding IsProcessing}"
            IsRunning="{Binding IsProcessing}"/>

    </AbsoluteLayout>
</pages:BasePage>
public abstract partial class BaseScanPage : BasePage
{
    readonly BaseScanViewModel _viewModel;

    public BaseScanPage(BaseScanViewModel viewModel) : base(viewModel)
    {
        _viewModel = viewModel;

        InitializeComponent();

        Unloaded += ContentPage_Unloaded;
        BarcodeView.OnDetectionFinished += BarcodeView_OnDetectionFinished;
    }

    protected override void OnAppearing()
    {
        base.OnAppearing();

        BarcodeView.CameraEnabled = true;
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        BarcodeView.CameraEnabled = false;
    }

    private async void BarcodeView_OnDetectionFinished(
        object? sender,
        OnDetectionFinishedEventArg e)
    {
        if (e.BarcodeResults.Length > 0)
        {
            await _viewModel.BarcodesDetectedCommand
                .ExecuteAsync(e.BarcodeResults.Select(b => b.RawValue));
        }
    }

    private void ContentPage_Unloaded(object? sender, EventArgs e)
    {
        BarcodeView.Handler?.DisconnectHandler();
    }
afriscic commented 1 month ago

Hello.

Sorry I currently don't have tome to test this properly but my guess is that when you go to second BarcodeView the Handler and underlying native Views from the first BarcodeView get disposed (DisconnectHandler() gets called) but the first BarcodeView doest not get disposed. So when you go back to the first BarcodeView you get the same instance but there is no Handler for it. Try to to the same navigation just with BarcodeView.Handler?.DisconnectHandler(); commented out. If this works than you have a solution, you just need to find a more appropriate place to call DisconnectHandler() or do some check to see if the Handler needs to get disposed.