Я использовал zxing.maui nuget для сканирования QR -кода, однако он не работает для некоторых небольших QR -кодов. После некоторого копания я обнаружил, что AvcaptureSession с iavcapturemetadataoutputobjectsdelegate работает для этого. Я имею в виду Vinodios/Swiftqrcodescanner для достижения этого. В отладке я вижу представление создается, а захват, однако, пользовательский интерфейс не показывает предварительного просмотра камеры. Я также пытался добавить эту zxing.maui fork, но iavcapturemetadataoutputobjectsdelegate.didoutputmetadataobjects не попадает там даже при [Export ("CaptureOutput: DidOutputMetAdataObjects: FromConnection:")] . Я посмотрел, как они добавляют sublayering VideoPreviewLayer в библиотеке ZXING.MAUI, а также попробовали это здесь (см. MayoutoutSubviews () ниже). Это также не показывает пользовательского интерфейса.
Я делаю что -то не так, очевидно. Не могу выяснить, что. < /P>
Я использовал zxing.maui nuget для сканирования QR -кода, однако он не работает для некоторых небольших QR -кодов. После некоторого копания я обнаружил, что AvcaptureSession с iavcapturemetadataoutputobjectsdelegate работает для этого. Я имею в виду Vinodios/Swiftqrcodescanner для достижения этого. В отладке я вижу представление создается, а захват, однако, пользовательский интерфейс не показывает предварительного просмотра камеры. Я также пытался добавить эту zxing.maui fork, но iavcapturemetadataoutputobjectsdelegate.didoutputmetadataobjects не попадает там даже при [Export ("CaptureOutput: DidOutputMetAdataObjects: FromConnection:")] . Я посмотрел, как они добавляют sublayering VideoPreviewLayer в библиотеке ZXING.MAUI, а также попробовали это здесь (см. MayoutoutSubviews () ниже). Это также не показывает пользовательского интерфейса. Я делаю что -то не так, очевидно. Не могу выяснить, что. < /P> [code]public class QRCodeReaderView : View { public static readonly BindableProperty IsScanningProperty = BindableProperty.Create(nameof(IsScanning), typeof(bool), typeof(CameraView), true);
public bool IsScanning { get => (bool)GetValue(IsScanningProperty); set => SetValue(IsScanningProperty, value); }
public event EventHandler? OnBarcodeDetected;
public void RaiseBarcodeDetected(string barcode) { OnBarcodeDetected?.Invoke(this, new BarcodeDetectedEventArgs(barcode)); } } < /code> public partial class QRCodeReaderViewHandler : ViewHandler { protected override IosQRCodeReaderView CreatePlatformView() { var control = new IosQRCodeReaderView(); return control; }
< /code> Нативный представление < /p> using System.Diagnostics; using AVFoundation; using CoreAnimation; using CoreFoundation; using Foundation; using UIKit;
namespace QRCodeScanner;
public class IosQRCodeReaderView : UIView, IAVCaptureMetadataOutputObjectsDelegate { private readonly AVCaptureDevice? _defaultDevice; private AVCaptureInput? _defaultCaptureInput => _defaultDevice is not null ? AVCaptureDeviceInput.FromDevice(_defaultDevice) : null; private readonly AVCaptureMetadataOutput _dataOutput; private readonly AVCaptureSession _captureSession; private readonly AVCaptureDevicePosition _devicePosition = AVCaptureDevicePosition.Back;
private void SetupCaptureSession() { if (_captureSession.Running) { return; } _captureSession.BeginConfiguration(); switch (_devicePosition) { case AVCaptureDevicePosition.Front:
//TODO break; case AVCaptureDevicePosition.Unspecified: case AVCaptureDevicePosition.Back: if (_defaultCaptureInput is not null && _captureSession.CanAddInput(_defaultCaptureInput)) { _captureSession.AddInput(_defaultCaptureInput); } break; default: Debug.WriteLine("Do nothing"); break; }
if (_captureSession.CanAddOutput(_dataOutput) is false) { return; } _captureSession.AddOutput(_dataOutput); _dataOutput.MetadataObjectTypes = _dataOutput.AvailableMetadataObjectTypes; _dataOutput.SetDelegate(this, DispatchQueue.MainQueue); Debug.WriteLine(_dataOutput.AvailableMetadataObjectTypes); _captureSession.CommitConfiguration(); }
private int _delayCount = 0; private const int MaxDelayCount = 15;
[Export("captureOutput:didOutputMetadataObjects:fromConnection:")] public void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection) { try { foreach (var data in metadataObjects) { if (_videoPreviewLayer.GetTransformedMetadataObject(data) is not AVMetadataMachineReadableCodeObject transformed) continue; if (Bounds.Contains(transformed.Bounds) is false || _videoPreviewLayer.Bounds.Contains(transformed.Bounds) is false) continue; _delayCount += 1; if (_delayCount < MaxDelayCount) continue; if (string.IsNullOrEmpty(transformed.StringValue)) continue; QRCodeDetected?.Invoke(this, new QRCodeEventArgs(transformed.StringValue)); _captureSession.StopRunning(); } } catch (Exception ex) { Debug.WriteLine(ex.StackTrace); } } } < /code> Назначение обработчика < /p> builder.ConfigureMauiHandlers(handlers => { handlers.AddHandler();
}); < /code>
< /code> private async Task CheckAndRequestCameraPermission() { var status = await Permissions.CheckStatusAsync(); if (status != PermissionStatus.Granted) { status = await Permissions.RequestAsync(); if (status != PermissionStatus.Granted) { await DisplayAlert("Camera Permission Denied", "This app needs access to the camera to scan QR codes.", "OK"); return; // Or disable the scanning functionality } } }