Я делаю что -то не так, очевидно. Не могу выяснить, что. < /P>
Код: Выделить всё
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;
}
private static void MapIsScanning(QRCodeReaderViewHandler handler, QRCodeReaderView qrCodeReaderView)
{
}
private static void MapOnBarcodeDetected(QRCodeReaderViewHandler handler, QRCodeReaderView qrCodeReaderView, object? args)
{
//TODO
}
}
< /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;
public event EventHandler? QRCodeDetected;
private readonly AVCaptureVideoPreviewLayer _videoPreviewLayer;
public IosQRCodeReaderView(AVCaptureDevicePosition position = AVCaptureDevicePosition.Back)
{
_defaultDevice = AVCaptureDevice.GetDefaultDevice(AVMediaTypes.Video);
_captureSession = new AVCaptureSession();
_devicePosition = position;
_dataOutput = new AVCaptureMetadataOutput();
_videoPreviewLayer = new AVCaptureVideoPreviewLayer(_captureSession)
{
VideoGravity = AVLayerVideoGravity.ResizeAspectFill,
CornerRadius = 10.0f,
};
PrepareQRScanner();
StartScanningQRCode();
}
public override void LayoutSubviews()
{
base.LayoutSubviews();
var transform = CATransform3D.MakeRotation(0, 0, 0, 1.0f);
switch (UIDevice.CurrentDevice.Orientation)
{
case UIDeviceOrientation.Portrait:
transform = CATransform3D.MakeRotation(0, 0, 0, 1.0f);
break;
case UIDeviceOrientation.PortraitUpsideDown:
transform = CATransform3D.MakeRotation((nfloat)Math.PI, 0, 0, 1.0f);
break;
case UIDeviceOrientation.LandscapeLeft:
transform = CATransform3D.MakeRotation((nfloat)(-Math.PI / 2), 0, 0, 1.0f);
break;
case UIDeviceOrientation.LandscapeRight:
transform = CATransform3D.MakeRotation((nfloat)Math.PI / 2, 0, 0, 1.0f);
break;
case UIDeviceOrientation.Unknown:
case UIDeviceOrientation.FaceUp:
case UIDeviceOrientation.FaceDown:
default:
break;
}
_videoPreviewLayer.Transform = transform;
_videoPreviewLayer.Frame = Layer.Bounds;
AddMaskToVideoPreviewLayer();
}
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 void PrepareQRScanner()
{
SetupCaptureSession();
}
private AVCaptureDeviceInput? GetCurrentInput()
{
if (_captureSession.Inputs.FirstOrDefault() is AVCaptureDeviceInput deviceInput)
{
return deviceInput;
}
return null;
}
private void StartScanningQRCode()
{
if (_captureSession.Running)
{
return;
}
//DispatchQueue.GetGlobalQueue(DispatchQualityOfService.Background).DispatchAsync(_captureSession.StartRunning);
MainThread.BeginInvokeOnMainThread(_captureSession.StartRunning);
}
private void AddMaskToVideoPreviewLayer()
{
//TODO: add
}
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
}
}
}
protected override async void OnAppearing()
{
base.OnAppearing();
await CheckAndRequestCameraPermission();
}
Подробнее здесь: https://stackoverflow.com/questions/794 ... displaying