我有一个CameraHelper类,专门为每个平台实现。在iOS中,我希望在CameraHelper中有一个所谓的ScanId函数,如下所示:
public override Task<ImageData> ScanId(PictureQuality quality)
{
_quality = quality;
_scanIdViewController = new ScanIdViewController();
_scanIdViewController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
_scanIdViewController.ImagePicked += CustomCam_ImagePicked;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var rootController = window.RootViewController;
while (rootController.PresentedViewController != null)
rootController = rootController.PresentedViewController;
rootController.PresentViewController(_scanIdViewController, true, null);
_imageDataPickedCompletionSource = new TaskCompletionSource<ImageData> { };
return _imageDataPickedCompletionSource.Task;
}
private void CustomCam_ImagePicked(object sender, EventArgs e)
{
if (sender is ScanIdViewController scanIdController && scanIdController.Image is { })
{
using (NSData imageData = scanIdController.Image.AsPNG())
{
byte[] data = new byte[imageData.Length];
Marshal.Copy(imageData.Bytes, data, 0, Convert.ToInt32(imageData.Length));
var scaledBytes = GetScaledImage(data);
_imageDataPickedCompletionSource.SetResult(new ImageData(scaledBytes, null, RotationNeeded(GetPicInfo(data)), true));
};
}
}
字符串
则ScanIdViewController:
public class ScanIdViewController: UIViewController
{
public event EventHandler ImagePicked;
public UIImage Image { get; private set; }
private PhotoCaptureDelegate _delegate;
private AVCaptureSession _captureSession;
private CGRect _outlineRect;
IExceptionHandler _exceptionHandler = DependencyContainer.Current.Resolve<IExceptionHandler>();
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Create a new AVCaptureSession
_captureSession = new AVCaptureSession() { SessionPreset = AVCaptureSession.PresetPhoto };
// Set the capture session's preset to high quality
_captureSession.SessionPreset = AVCaptureSession.PresetHigh;
// Get the back camera device
var backCamera = AVCaptureDevice.GetDefaultDevice(AVCaptureDeviceType.BuiltInWideAngleCamera, AVMediaTypes.Video, AVCaptureDevicePosition.Back);
// Create a new AVCaptureDeviceInput using the back camera
var input = AVCaptureDeviceInput.FromDevice(backCamera);
// Add the input to the capture session
_captureSession.AddInput(input);
// Create a new AVCaptureVideoPreviewLayer
var previewLayer = new AVCaptureVideoPreviewLayer(_captureSession);
SetupPreviewLayer(previewLayer);
var capturePhotoOutput = new AVCapturePhotoOutput();
_delegate = new PhotoCaptureDelegate();
_delegate.ImagePicked += PhotoCaptureDelegate_ImagePicked;
_captureSession.AddOutput(capturePhotoOutput);
var captureButton = new UIButton(UIButtonType.System);
captureButton.Frame = new CGRect(0, 0, 50, 50);
captureButton.Center = new CGPoint(View.Bounds.GetMidX(), View.Bounds.GetMaxY() - 50);
captureButton.BackgroundColor = UIColor.White;
captureButton.Layer.CornerRadius = 25;
captureButton.TouchUpInside += (sender, e) =>
{
var photoSettings = AVCapturePhotoSettings.Create();
capturePhotoOutput.CapturePhoto(photoSettings, _delegate);
};
View.AddSubview(captureButton);
_captureSession.StartRunning();
}
private void PhotoCaptureDelegate_ImagePicked(object sender, EventArgs e)
{
if (sender is PhotoCaptureDelegate del && del.Image is { })
{
var bounds = UIScreen.MainScreen.Bounds;
var aspectX = del.Image.Size.Width / bounds.Width;
var aspectY = del.Image.Size.Height / bounds.Height;
var cutImage = del.Image.CropImage((int)(_outlineRect.X * aspectX), (int)(_outlineRect.Y * aspectY), (int)(_outlineRect.Width * aspectX), (int)(_outlineRect.Height * aspectY));
var previewImageView = new UIImageView(new CGRect(0, 0, UIScreen.MainScreen.Bounds.Width, UIScreen.MainScreen.Bounds.Height - 100)) { Image = cutImage };
var previewController = new PreviewImageViewController(previewImageView);
previewController.ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
previewController.ImageAccepted += PreviewController_ImageAccepted;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var rootController = window.RootViewController;
while (rootController.PresentedViewController != null)
rootController = rootController.PresentedViewController;
rootController.PresentViewController(previewController, true, null);
}
}
private void PreviewController_ImageAccepted(object sender, EventArgs e)
{
Image = _delegate.Image;
ImagePicked?.Invoke(this, EventArgs.Empty);
if (_captureSession.Running)
{
Device.BeginInvokeOnMainThread(() => _captureSession.StopRunning());
Device.BeginInvokeOnMainThread(() => DismissModalViewController(true));
}
}
private void SetupPreviewLayer(AVCaptureVideoPreviewLayer avCapturePreviewLayer)
{
avCapturePreviewLayer.VideoGravity = AVLayerVideoGravity.ResizeAspectFill;
avCapturePreviewLayer.Connection.VideoOrientation = AVCaptureVideoOrientation.Portrait;
avCapturePreviewLayer.Frame = UIScreen.MainScreen.Bounds;
View.Layer.InsertSublayer(avCapturePreviewLayer, 0);
var overlay = CreateImageOverlay();
View.AddSubview(overlay);
}
型
然后是PreviewImageViewController:
public class PreviewImageViewController : UIViewController
{
private UIImageView _previewImageView;
public event EventHandler ImageAccepted;
public PreviewImageViewController(UIImageView previewImageView)
{
_previewImageView = previewImageView;
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
SetUpPreviewImageView();
}
private void SetUpPreviewImageView()
{
_previewImageView.ContentMode = UIViewContentMode.ScaleAspectFit;
UIButton acceptButton = new UIButton();
acceptButton.SetTitle("Foto verwenden", UIControlState.Normal);
acceptButton.SetTitleColor(UIColor.White, UIControlState.Normal);
acceptButton.BackgroundColor = UIColor.Black;
acceptButton.Frame = new CGRect(0, View.Frame.Height - 100, View.Frame.Width / 2, 100);
acceptButton.SetTitleColor(UIColor.White, UIControlState.Normal);
acceptButton.TouchUpInside += (sender, e) =>
{
_previewImageView.Image = _previewImageView.Image;
ImageAccepted?.Invoke(this, EventArgs.Empty);
DismissModalViewController(true);
};
UIButton retakeButton = new UIButton();
retakeButton.Frame = new CGRect(View.Frame.Width / 2, View.Frame.Height - 100, View.Frame.Width / 2, 100);
retakeButton.SetTitle("Wiederholen", UIControlState.Normal);
retakeButton.SetTitleColor(UIColor.White, UIControlState.Normal);
retakeButton.BackgroundColor = UIColor.Black;
retakeButton.TouchUpInside += (sender, e) =>
{
DismissModalViewController(true);
};
View.AddSubview(_previewImageView);
View.Add(acceptButton);
View.Add(retakeButton);
}
}
型
问题是PreviewImageViewController被正确地解除了,但是即使Device.BeginInvokeOnMainThread(()=> DismissModalViewController(true));在ScanIdViewController.PreviewController_ImageAccepted中调用,视图在相机视图上保持冻结,覆盖,在这种情况下按钮不起作用。
我真的希望关闭查看/捕获会话并返回到下面的视图(在CameraHelper中调用ScanId之前)
1条答案
按热度按时间u5rb5r591#
好了,通过更改在PreviewImageViewController上调用ImageAccepted的时间来解决这个问题-在ViewDidDisappear中:
字符串
然后将以下内容添加到ScanIdViewController:
型