BarcodeScanner.Mobile icon indicating copy to clipboard operation
BarcodeScanner.Mobile copied to clipboard

CameraView does not appear to respect HeightRequest or WidthRequest

Open ThreeSevenths opened this issue 2 years ago • 3 comments

Describe the bug When using the <gv:CameraView /> View, the WidthRequest and HeightRequest properties do not seem to be respected properly. Adding a border around the CameraView only makes the situation worse and no camera preview is displayed.

To Reproduce Steps to reproduce the behavior:

https://github.com/ThreeSevenths/ReproSampleBarcodePopover

Clone and Run the repro sample.

Expected behavior

I expect that the Width and Height requested can be observed, or should at least throw if they cannot be. I also expect the CameraView to work in a Border, or in a Community Toolkit PopupView without overflowing the container.

Smartphone (please complete the following information):

  • Device: Samsung Galaxy Tablet
  • OS: Android
  • Version Maui 7.0

ThreeSevenths avatar Sep 21 '23 20:09 ThreeSevenths

Any updates on this, or fix?

roxton001 avatar Nov 15 '24 14:11 roxton001

I've ended up making my own popup control that's sized to the natural size/ratio of the camera. It seems to work well enough for my tablet use case. If there is clipping or stretching it's not a major issue for what I am doing.

using BarcodeScanner.Mobile;
using CommunityToolkit.Maui.Markup;
using CommunityToolkit.Maui.Views;
using static CommunityToolkit.Maui.Markup.GridRowsColumns;

public class BarcodeScannerPopup : Popup, IDisposable
{
    private bool disposedValue;

    private CameraView CameraView;
    private Button ToggleFlashlight;
    private Grid TheGrid;

    public BarcodeScannerPopup()
    {
        ResultWhenUserTapsOutsideOfPopup = string.Empty;

        Content = new VerticalStackLayout
        {
            Children = {
                new Border
                {
                    Stroke = SolidColorBrush.Transparent,
                    StrokeThickness = 0,
                    Content = new Grid
                    {
                        RowDefinitions = Rows.Define(Star),
                        Children = {
                            new CameraView
                            {
                                CaptureQuality = CaptureQuality.Low
                            }
                            .Size(720, 480)
                            .Row(0)
                            .Assign(out CameraView),
                            new Border
                            {
                                StrokeThickness = 0,
                                Stroke = SolidColorBrush.Transparent,
                                Background = SolidColorBrush.Transparent
                            }
                                .Fill(),
                            new Button()
                            {
                                HorizontalOptions = LayoutOptions.Start,
                                VerticalOptions = LayoutOptions.Start,
                            }
                                .Text("Toggle Flashlight")
                                .Assign(out ToggleFlashlight)
                                .Margin(10)

                        }
                    }
                    .MinSize(640, 480)
                    .Assign(out TheGrid)
                }
            }
        };

        CameraView.OnDetected += CameraView_OnDetected;
    }

    private void CameraView_OnDetected(object sender, OnDetectedEventArg e)
    {
        if (e?.BarcodeResults?.Count == 1)
        {
            this.Close(e.BarcodeResults.FirstOrDefault()?.RawValue);
        }
        else
        {
            CameraView.IsScanning = true;
        }
    }

    private void ToggleFlashlight_Clicked(object sender, EventArgs e)
    {
        if (null != CameraView)
        {
            CameraView.TorchOn = !CameraView.TorchOn;
        }
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects)
                if (null != TheGrid)
                {
                    do
                    {
                        TheGrid.Children.RemoveAt(0);
                    }
                    while (TheGrid.Children.Count > 0);
                }
            }

            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
            // TODO: set large fields to null
            disposedValue = true;
        }
    }

    // // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
    // ~BarcodeScannerPopup()
    // {
    //     // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
    //     Dispose(disposing: false);
    // }

    public void Dispose()
    {
        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
        Dispose(disposing: true);
        GC.SuppressFinalize(this);
    }
}

ThreeSevenths avatar Nov 15 '24 15:11 ThreeSevenths

Do we know if this issue got resolved/a workaround? Due to my use-case I'm not really able to put it in a separate dialog window, I need it to be embedded within the page and this is preventing me from continuing.

burnmw1987 avatar Jun 10 '25 15:06 burnmw1987