iOS VideoPreview格局颠倒

时间:2017-11-03 21:09:05

标签: ios xamarin xamarin.ios avcam

出于某种原因,当我将手机定位到横向模式时,相机预览会颠倒(水平翻转)。我正在使用Xamarin移植的示例项目; AVCamBarcode

我最终通过横向使用GeometryFlip来完成半个完整的修复。但是,现在绘制的条形码不会以横向模式在正确的位置绘制。

  1. 这是设备/操作系统问题还是样本不完整?
  2. 建议的解决方法是什么?

    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 ();
            });
        }
    }
    
  3. 修改

    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 ();
        }
    }
    

1 个答案:

答案 0 :(得分:1)

设备和视频方向对景观有不同的含义。

The docs say (for video)

  

案例landscapeLeft

     

表示视频应水平定向,位于右上方。

     

案例landscapeRight

     

表示视频应水平定向,位于左上方。

device orientation说:

  

案例landscapeLeft

     

设备处于横向模式,设备直立,主页按钮位于右侧。

     

案例landscapeRight

     

设备处于横向模式,设备直立,主页按钮位于左侧。

所以,你需要改为:

case UIDeviceOrientation.LandscapeLeft:
    return LandscapeRight;
case UIDeviceOrientation.LandscapeRight:
    return LandscapeLeft;