iOS VideoPreview Landscape 颠倒了
iOS VideoPreview Landscape is upside down
出于某种原因,当我将 phone 设置为横向模式时,相机预览倒置(水平翻转)。我正在使用 Xamarin 移植的示例项目; AVCamBarcode.
我最终通过横向使用 GeometryFlipped 完成了一半的修复。但是,现在绘制的条形码在横向模式下没有绘制在正确的位置。
- 这是 device/os 问题还是样本不完整?
推荐的纠正方法是什么?
public override void ViewWillTransitionToSize (CGSize toSize, IUIViewControllerTransitionCoordinator coordinator)
{
base.ViewWillTransitionToSize (toSize, coordinator);
var videoPreviewLayerConnection = PreviewView.VideoPreviewLayer.Connection;
if (videoPreviewLayerConnection != null) {
var deviceOrientation = UIDevice.CurrentDevice.Orientation;
if (!deviceOrientation.IsPortrait () && !deviceOrientation.IsLandscape ())
return;
var newVideoOrientation = VideoOrientationFor (deviceOrientation);
var oldSize = View.Frame.Size;
var oldVideoOrientation = videoPreviewLayerConnection.VideoOrientation;
videoPreviewLayerConnection.VideoOrientation = newVideoOrientation;
//THIS IS THE HALF FIX I CAME UP WITH
if (deviceOrientation.IsLandscape())
videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = true;
else
videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = false;
//END FIX
// When we transition to the new size, we need to adjust the region
// of interest's origin and size so that it stays anchored relative
// to the camera.
coordinator.AnimateAlongsideTransition (context => {
var oldRegion = PreviewView.RegionOfInterest;
var newRegion = new CGRect ();
if (oldVideoOrientation == LandscapeRight && newVideoOrientation == LandscapeLeft) {
newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width);
} else if (oldVideoOrientation == LandscapeRight && newVideoOrientation == Portrait) {
newRegion.X = toSize.Width - oldRegion.Y - oldRegion.Height;
newRegion.Y = oldRegion.X;
newRegion.Width = oldRegion.Height;
newRegion.Height = oldRegion.Width;
} else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == LandscapeRight) {
newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width);
} else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == Portrait) {
newRegion.X = oldRegion.Y;
newRegion.Y = oldSize.Width - oldRegion.X - oldRegion.Width;
newRegion.Width = oldRegion.Height;
newRegion.Height = oldRegion.Width;
} else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeRight) {
newRegion.X = oldRegion.Y;
newRegion.Y = toSize.Height - oldRegion.X - oldRegion.Width;
newRegion.Width = oldRegion.Height;
newRegion.Height = oldRegion.Width;
} else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeLeft) {
newRegion.X = oldSize.Height - oldRegion.Y - oldRegion.Height;
newRegion.Y = oldRegion.X;
newRegion.Width = oldRegion.Height;
newRegion.Height = oldRegion.Width;
}
PreviewView.SetRegionOfInterestWithProposedRegionOfInterest (newRegion);
}, context => {
sessionQueue.DispatchAsync (() => {
metadataOutput.RectOfInterest = PreviewView.VideoPreviewLayer.MapToLayerCoordinates (PreviewView.RegionOfInterest);
});
// Remove the old metadata object overlays.
RemoveMetadataObjectOverlayLayers ();
});
}
}
编辑
AVCaptureVideoOrientation VideoOrientationFor (UIDeviceOrientation deviceOrientation)
{
switch (deviceOrientation) {
case UIDeviceOrientation.Portrait:
return Portrait;
case UIDeviceOrientation.PortraitUpsideDown:
return PortraitUpsideDown;
case UIDeviceOrientation.LandscapeLeft:
return LandscapeLeft;
case UIDeviceOrientation.LandscapeRight:
return LandscapeRight;
default:
throw new InvalidProgramException ();
}
}
设备和视频方向对于横向具有不同的含义。
case landscapeLeft
Indicates that video should be oriented horizontally, top on the right.
case landscapeRight
Indicates that video should be oriented horizontally, top on the left.
但是 device orientation 说:
case landscapeLeft
The device is in landscape mode, with the device held upright and the home button on the right side.
case landscapeRight
The device is in landscape mode, with the device held upright and the home button on the left side.
因此,您需要更改为:
case UIDeviceOrientation.LandscapeLeft:
return LandscapeRight;
case UIDeviceOrientation.LandscapeRight:
return LandscapeLeft;
出于某种原因,当我将 phone 设置为横向模式时,相机预览倒置(水平翻转)。我正在使用 Xamarin 移植的示例项目; AVCamBarcode.
我最终通过横向使用 GeometryFlipped 完成了一半的修复。但是,现在绘制的条形码在横向模式下没有绘制在正确的位置。
- 这是 device/os 问题还是样本不完整?
推荐的纠正方法是什么?
public override void ViewWillTransitionToSize (CGSize toSize, IUIViewControllerTransitionCoordinator coordinator) { base.ViewWillTransitionToSize (toSize, coordinator); var videoPreviewLayerConnection = PreviewView.VideoPreviewLayer.Connection; if (videoPreviewLayerConnection != null) { var deviceOrientation = UIDevice.CurrentDevice.Orientation; if (!deviceOrientation.IsPortrait () && !deviceOrientation.IsLandscape ()) return; var newVideoOrientation = VideoOrientationFor (deviceOrientation); var oldSize = View.Frame.Size; var oldVideoOrientation = videoPreviewLayerConnection.VideoOrientation; videoPreviewLayerConnection.VideoOrientation = newVideoOrientation; //THIS IS THE HALF FIX I CAME UP WITH if (deviceOrientation.IsLandscape()) videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = true; else videoPreviewLayerConnection.VideoPreviewLayer.GeometryFlipped = false; //END FIX // When we transition to the new size, we need to adjust the region // of interest's origin and size so that it stays anchored relative // to the camera. coordinator.AnimateAlongsideTransition (context => { var oldRegion = PreviewView.RegionOfInterest; var newRegion = new CGRect (); if (oldVideoOrientation == LandscapeRight && newVideoOrientation == LandscapeLeft) { newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width); } else if (oldVideoOrientation == LandscapeRight && newVideoOrientation == Portrait) { newRegion.X = toSize.Width - oldRegion.Y - oldRegion.Height; newRegion.Y = oldRegion.X; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == LandscapeRight) { newRegion = oldRegion.WithX (oldSize.Width - oldRegion.X - oldRegion.Width); } else if (oldVideoOrientation == LandscapeLeft && newVideoOrientation == Portrait) { newRegion.X = oldRegion.Y; newRegion.Y = oldSize.Width - oldRegion.X - oldRegion.Width; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeRight) { newRegion.X = oldRegion.Y; newRegion.Y = toSize.Height - oldRegion.X - oldRegion.Width; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } else if (oldVideoOrientation == Portrait && newVideoOrientation == LandscapeLeft) { newRegion.X = oldSize.Height - oldRegion.Y - oldRegion.Height; newRegion.Y = oldRegion.X; newRegion.Width = oldRegion.Height; newRegion.Height = oldRegion.Width; } PreviewView.SetRegionOfInterestWithProposedRegionOfInterest (newRegion); }, context => { sessionQueue.DispatchAsync (() => { metadataOutput.RectOfInterest = PreviewView.VideoPreviewLayer.MapToLayerCoordinates (PreviewView.RegionOfInterest); }); // Remove the old metadata object overlays. RemoveMetadataObjectOverlayLayers (); }); } }
编辑
AVCaptureVideoOrientation VideoOrientationFor (UIDeviceOrientation deviceOrientation)
{
switch (deviceOrientation) {
case UIDeviceOrientation.Portrait:
return Portrait;
case UIDeviceOrientation.PortraitUpsideDown:
return PortraitUpsideDown;
case UIDeviceOrientation.LandscapeLeft:
return LandscapeLeft;
case UIDeviceOrientation.LandscapeRight:
return LandscapeRight;
default:
throw new InvalidProgramException ();
}
}
设备和视频方向对于横向具有不同的含义。
case landscapeLeft
Indicates that video should be oriented horizontally, top on the right.
case landscapeRight
Indicates that video should be oriented horizontally, top on the left.
但是 device orientation 说:
case landscapeLeft
The device is in landscape mode, with the device held upright and the home button on the right side.
case landscapeRight
The device is in landscape mode, with the device held upright and the home button on the left side.
因此,您需要更改为:
case UIDeviceOrientation.LandscapeLeft:
return LandscapeRight;
case UIDeviceOrientation.LandscapeRight:
return LandscapeLeft;