首页 文章

AVCaptureVideoPreviewLayer方向 - 需要景观

提问于
浏览
54

我的应用只是风景 . 我将这样呈现AVCaptureVideoPreviewLayer:

self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
[self.previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
[self.previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];                    
NSLog(@"previewView: %@", self.previewView);
CALayer *rootLayer = [self.previewView layer];
[rootLayer setMasksToBounds:YES];
[self.previewLayer setFrame:[rootLayer bounds]];
    NSLog(@"previewlayer: %f, %f, %f, %f", self.previewLayer.frame.origin.x, self.previewLayer.frame.origin.y, self.previewLayer.frame.size.width, self.previewLayer.frame.size.height);
[rootLayer addSublayer:self.previewLayer];
[session startRunning];

self.previewView的框架为(0,0,568,320),这是正确的 . self.previewLayer记录一个(0,0,568,320)的帧,这在理论上是正确的 . 但是,相机显示在横向屏幕中间显示为纵向矩形,并且相机预览图像的方向错误90度 . 我究竟做错了什么?我需要在横屏模式下以全屏显示相机预览图层,并且图像应正确定向 .

17 回答

  • 10

    默认摄像机方向为横向左侧(左侧是主页按钮) . 你需要在这里做两件事:

    1-将previewLayer框架更改为:

    self.previewLayer.frame=self.view.bounds;
    

    您需要将预览图层框架设置为屏幕边界,以便在屏幕旋转时预览图层的框架发生更改(您不能使用根视图的框架,因为它不会随着旋转而改变,而是根视图的边界做) . 在您的示例中,您将预览层框架设置为我看不到的previewView属性 .

    2-您需要通过设备的旋转来旋转预览图层连接 . 在viewDidAppear中添加此代码:

    -(void) viewDidAppear:(BOOL)animated
    {
      [super viewDidAppear:YES];
    
      //Get Preview Layer connection
      AVCaptureConnection *previewLayerConnection=self.previewLayer.connection;
    
      if ([previewLayerConnection isVideoOrientationSupported])
        [previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]]; 
    }
    

    希望这能解决它 .

    完全披露:这是一个简化版本,因为您不关心Landscape Right还是Landscape .

  • 1

    SWIFT 3.0和XCODE 8.0的最佳答案

    private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
    
        layer.videoOrientation = orientation
    
        previewLayer.frame = self.view.bounds
    
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        if let connection =  self.previewLayer?.connection  {
    
            let currentDevice: UIDevice = UIDevice.current
    
            let orientation: UIDeviceOrientation = currentDevice.orientation
    
            let previewLayerConnection : AVCaptureConnection = connection
    
            if previewLayerConnection.isVideoOrientationSupported {
    
                switch (orientation) {
                case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
    
                    break
    
                case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
    
                    break
    
                case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
    
                    break
    
                case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
    
                    break
    
                default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
    
                    break
                }
            }
        }
    }
    

    BEST ANSWER FOR SWIFT 2.2 AND XCODE 7.3

    private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
    
        layer.videoOrientation = orientation
    
        previewLayer.frame = self.view.bounds
    
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        if let connection =  self.previewLayer?.connection  {
    
            let currentDevice: UIDevice = UIDevice.currentDevice()
    
            let orientation: UIDeviceOrientation = currentDevice.orientation
    
            let previewLayerConnection : AVCaptureConnection = connection
    
            if (previewLayerConnection.supportsVideoOrientation) {
    
                switch (orientation) {
                case .Portrait: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)
    
                    break
    
                case .LandscapeRight: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeLeft)
    
                    break
    
                case .LandscapeLeft: updatePreviewLayer(previewLayerConnection, orientation: .LandscapeRight)
    
                    break
    
                case .PortraitUpsideDown: updatePreviewLayer(previewLayerConnection, orientation: .PortraitUpsideDown)
    
                    break
    
                default: updatePreviewLayer(previewLayerConnection, orientation: .Portrait)
    
                    break
                }
            }
        }
    }
    
  • 0
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
        if let connection =  self.previewLayer?.connection  {
            var currentDevice: UIDevice = UIDevice.currentDevice()
            var orientation: UIDeviceOrientation = currentDevice.orientation
            var previewLayerConnection : AVCaptureConnection = connection
    
            if (previewLayerConnection.supportsVideoOrientation) {
                switch (orientation) {
                case .portrait:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
                    break
                case .landscapeRight:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeRight
                    break
                case .landscapeLeft:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
                    break
                case .portraitUpsideDown:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
                    break
    
                default:
                    previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.portrait
                    break
                }
            }
        }
    }
    
  • 2

    我们不能用

    [previewLayerConnection setVideoOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
    

    因为 UIInterfaceOrientation != AVCaptureVideoOrientation

    但是我们可以通过以下代码测试值...并且这项工作 .

    -(void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        switch (orientation) {
            case UIInterfaceOrientationPortrait:
                [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
                break;
            case UIInterfaceOrientationPortraitUpsideDown:
                [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
                break;
            case UIInterfaceOrientationLandscapeLeft:
                [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
                break;
            case UIInterfaceOrientationLandscapeRight:
                [_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
                break;
        }
    }
    
  • 4

    API似乎有所改变 . videoOrientation 现在是预览图层 connection 属性的属性 . 此外,无需使用开关 . Swift 3.0的答案:

    override func viewDidLayoutSubviews() {
        self.configureVideoOrientation()
    }
    
    private func configureVideoOrientation() {
        if let previewLayer = self.previewLayer,
            let connection = previewLayer.connection {
            let orientation = UIDevice.current.orientation
    
            if connection.isVideoOrientationSupported,
                let videoOrientation = AVCaptureVideoOrientation(rawValue: orientation.rawValue) {
                previewLayer.frame = self.view.bounds
                previewLayer.connection?.videoOrientation = videoOrientation
            }
        }
    }
    
  • 0

    对于那些正在全功能相机预览中苦苦挣扎的人 . 这是 生产环境 代码 . 当然,缺点是方向改变时滞后 . 如果有人有更好的解决方案来克服这个,请分享

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self initCamera];
    }
    
    - (void)initCamera
    {
        AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
        if (captureInput) {
            mSession = [[AVCaptureSession alloc] init];
            [mSession addInput:captureInput];
        }
    }
    
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
        [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
        if ([mSession isRunning]) {
            [mSession stopRunning];
            [mCameraLayer removeFromSuperlayer];
    
            [self initCamera];
    
            [self startCamera];
        }
    }
    
    - (void)startCamera
    {
        [mSession startRunning];
        Settings::getInstance()->setClearColor(Color(0, 0, 0, 0));
        mCameraLayer = [AVCaptureVideoPreviewLayer layerWithSession: mSession];
        [self updateCameraLayer];
        [mCameraView.layer addSublayer:mCameraLayer];
    }
    
    - (void)stopCamera
    {
        [mSession stopRunning];
        [mCameraLayer removeFromSuperlayer];
        Settings::getInstance()->setDefClearColor();
    }
    
    - (void)toggleCamera
    {
        mSession.isRunning ? [self stopCamera] : [self startCamera];
        [mGLKView setNeedsDisplay];
    }
    
    - (void)updateCameraLayer
    {
        mCameraLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
        mCameraLayer.frame = mCameraView.bounds;
        float x = mCameraView.frame.origin.x;
        float y = mCameraView.frame.origin.y;
        float w = mCameraView.frame.size.width;
        float h = mCameraView.frame.size.height;
        CATransform3D transform = CATransform3DIdentity;
        if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
            mCameraLayer.frame = CGRectMake(x, y, h, w);
            transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
            transform = CATransform3DRotate(transform, -M_PI/2, 0, 0, 1);
        } else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation]) {
            mCameraLayer.frame = CGRectMake(x, y, h, w);
            transform = CATransform3DTranslate(transform, (w - h) / 2, (h - w) / 2, 0);
            transform = CATransform3DRotate(transform, M_PI/2, 0, 0, 1);
        } else if (UIDeviceOrientationPortraitUpsideDown == [[UIDevice currentDevice] orientation]) {
            mCameraLayer.frame = mCameraView.bounds;
            transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
        } else {
            mCameraLayer.frame = mCameraView.bounds;
        }
        mCameraLayer.transform  = transform;
    }
    
        enter code here
    
  • 7

    由于使用上述解决方案存在弃用和转换警告,并且设置videoOrientation似乎在iOS7中不起作用,因此我在AVCaptureVideoPreviewLayer的getter中检查了方向,如下所示:

    - (AVCaptureVideoPreviewLayer *) previewLayer
    {
        if(!_previewLayer)
        {
            _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession: self.captureSession];
    
        [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    
        _previewLayer.frame = self.view.bounds; // Assume you want the preview layer to fill the view.
    
        [_previewLayer setPosition:CGPointMake(0,0)];
    
        if (UIDeviceOrientationLandscapeLeft == [[UIDevice currentDevice] orientation]) {
            _previewLayer.transform = CATransform3DMakeRotation(-M_PI/2, 0, 0, 1);
        }
        else if (UIDeviceOrientationLandscapeRight == [[UIDevice currentDevice] orientation])
        {
            _previewLayer.transform = CATransform3DMakeRotation(M_PI/2, 0, 0, 1);
        }
    }
    
    return _previewLayer;
    }
    
  • 1

    适用于Swift 4,Xcode 9:

    override func viewWillTransition(to size: CGSize,
                                       with coordinator: UIViewControllerTransitionCoordinator)
      {
        super.viewWillTransition(to: size, with: coordinator)
        guard
        let conn = self.previewLayer?.connection,
          conn.isVideoOrientationSupported
          else { return }
        let deviceOrientation = UIDevice.current.orientation
        switch deviceOrientation {
        case .portrait: conn.videoOrientation = .portrait
        case .landscapeRight: conn.videoOrientation = .landscapeLeft
        case .landscapeLeft: conn.videoOrientation = .landscapeRight
        case .portraitUpsideDown: conn.videoOrientation = .portraitUpsideDown
        default: conn.videoOrientation = .portrait
        }
      }
    

    这里要注意的一个微妙之处是 UIDeviceOrientation.landscapeRightAVCaptureVideoOrientation.landscapeLeft 一起使用 .

    另一个景观案例同样不匹配 . 这是故意的,并且容纳了UIKit和AVFoundation之间不幸的不匹配 . 如果您通过匹配名称来匹配案例,则它将无效,并且您的视频将在横向配置中颠倒 .

  • 65

    嘿伙计们感谢所有的答案和反馈,我遇到了这个,因为我正在开发一个快速的应用程序 . 您可以使用以下代码将相机与设备一起旋转:

    override func shouldAutorotate() -> Bool {
            if your cameraController.previewLayer.connection != nil {
                var currentDevice: UIDevice = UIDevice.currentDevice()
                var orientation: UIDeviceOrientation = currentDevice.orientation
    
                var previewLayerConnection : AVCaptureConnection = your cameraController.previewLayer.connection
    
                if (previewLayerConnection.supportsVideoOrientation)
                {
                    switch (orientation)
                    {
                    case .Portrait:
                        previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
                        break
                    case .LandscapeRight:
                        previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
                        break
                    case .LandscapeLeft:
                        previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
                        break
                    default:
                        previewLayerConnection.videoOrientation = AVCaptureVideoOrientation.Portrait
                        break
                    }
                }
    
            }
            return true
        }
    

    希望这可以帮助!

  • 1

    UIDeviceOrientationAVCaptureVideoOrientation 的正确映射是必要的 .

    如果您的应用支持 device rotation ,则还需要 resizing preview.frame ,并且应从 viewDidLayoutSubviews()viewWillTransition() 调用此 func .

    private func configureVideoOrientation() {
        if let preview = self.previewLayer,
            let connection = preview.connection {
            let orientation = UIDevice.current.orientation
    
            if connection.isVideoOrientationSupported {
                var videoOrientation: AVCaptureVideoOrientation
                switch orientation {
                case .portrait:
                    videoOrientation = .portrait
                case .portraitUpsideDown:
                    videoOrientation = .portraitUpsideDown
                case .landscapeLeft:
                    videoOrientation = .landscapeRight
                case .landscapeRight:
                    videoOrientation = .landscapeLeft
                default:
                    videoOrientation = .portrait
                }
                preview.frame = self.view.bounds
                connection.videoOrientation = videoOrientation
            }
        }
    }
    
  • 3

    首先,我们需要创建AVCaptureVideoPreviewLayer并:

    • 设置了它的videoGravity(在我的情况下,我使用一个小视图来获取视频输出) .

    • 设置框架 .

    [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
    
    • 最初设置方向
    if (_videoPreviewLayer.connection.supportsVideoOrientation) {
            _videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
        }
    
    • 使用简单的开关盒设置每种情况的方向
    -(AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation: 
    
     (UIInterfaceOrientation)orientation {
    
        switch (orientation) {
            case UIInterfaceOrientationPortrait:
                return AVCaptureVideoOrientationPortrait;
            case UIInterfaceOrientationPortraitUpsideDown:
                return AVCaptureVideoOrientationPortraitUpsideDown;
            case UIInterfaceOrientationLandscapeLeft:
                return AVCaptureVideoOrientationLandscapeLeft ;
            case UIInterfaceOrientationLandscapeRight:
                return AVCaptureVideoOrientationLandscapeRight;
            default:
                break;
        }
        NSLog(@"Warning - Didn't recognise interface orientation (%d)",orientation);
        return AVCaptureVideoOrientationPortrait;
     
    
     }
    
    • 由于设备支持landscapeLeft和landscapeRight,因此使用旋转时调用的委托:
    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    if (_videoPreviewLayer.connection.supportsVideoOrientation) {
        _videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:toInterfaceOrientation];
     }
    }
    
  • 1

    我也是面对同样的这是为了修复我的相机方向

    override func shouldAutorotate() -> Bool {
            return false
        }
    
    override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
            return UIInterfaceOrientation.LandscapeLeft
        }
    
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
            return UIInterfaceOrientationMask.LandscapeLeft
        }
    

    修理相机

    let previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.avCaptureSession)    
    previewLayer.frame = self.view.layer.frame
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
    
  • 14

    Maselko's answer几乎为我工作,除了状态栏方向翻转然后相机输出显示颠倒 . 当状态栏翻转时,我've addressed that issue by re-calling Maselko'的逻辑 .

    这是我修改过的Maselko解决方案(在ios12 / swift4上测试):

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        setCameraOrientation()
    }
    
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        setCameraOrientation()
    }
    
    @objc func setCameraOrientation() {
        if let connection =  self.previewLayer?.connection  {
            let currentDevice: UIDevice = UIDevice.current
            let orientation: UIDeviceOrientation = currentDevice.orientation
            let previewLayerConnection : AVCaptureConnection = connection
            if previewLayerConnection.isVideoOrientationSupported {
                let o: AVCaptureVideoOrientation
                switch (orientation) {
                case .portrait: o = .portrait
                case .landscapeRight: o = .landscapeLeft
                case .landscapeLeft: o = .landscapeRight
                case .portraitUpsideDown: o = .portraitUpsideDown
                default: o = .portrait
                }
    
                previewLayerConnection.videoOrientation = o
                previewLayer!.frame = self.view.bounds
            }
        }
    }
    
  • 2

    选择的答案适用于Swift 4.2 - Xcode 10.0 - iOS 12.0:

    var videoPreviewLayer: AVCaptureVideoPreviewLayer?
    
    override func viewDidLayoutSubviews() {
      super.viewDidLayoutSubviews()
      if let previewLayerConnection =  self.videoPreviewLayer?.connection, previewLayerConnection.isVideoOrientationSupported {
        updatePreviewLayer(layer: previewLayerConnection, orientation: UIApplication.shared.statusBarOrientation.videoOrientation)
      }
    }
    
    private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
      layer.videoOrientation = orientation
      videoPreviewLayer?.frame = self.view.bounds
    }
    

    不要忘记从UIInterfaceOrientation到AVCaptureVideoOrientation的映射

    extension UIInterfaceOrientation {
    
      public var videoOrientation: AVCaptureVideoOrientation {
        switch self {
        case .portrait:
          return AVCaptureVideoOrientation.portrait
        case .landscapeRight:
          return AVCaptureVideoOrientation.landscapeRight
        case .landscapeLeft:
          return AVCaptureVideoOrientation.landscapeLeft
        case .portraitUpsideDown:
          return AVCaptureVideoOrientation.portraitUpsideDown
        default:
          return AVCaptureVideoOrientation.portrait
        }
      }
    
    }
    
  • 0

    它在iOS 8到11.1中对我没有任何问题的唯一方法是这样做,我应该提一下,在我的情况下,我只在横向模式下加载我的应用程序,但它应该在所有方向上工作 . (顺便说一句,你可以叠加通过imageview手动摄像头或任何你想要的方式容易)

    @interface ViewController (){
        AVCaptureVideoPreviewLayer * previewLayer;
        AVCaptureSession* session;
    }
    @property (weak, nonatomic) IBOutlet UIView *cameraPreviewView;
    
    
    -(void)viewDidLoad{
        AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] error:nil];
        if (captureInput) {
            session = [[AVCaptureSession alloc] init];
            [session addInput:captureInput];
        }
        previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:session];
        [previewLayer setBackgroundColor:[[UIColor blackColor] CGColor]];
        [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspect];
    
        CALayer *rootLayer = [self.cameraPreviewView layer];
        [rootLayer setMasksToBounds:YES];
        [previewLayer setFrame:[self.view bounds]];
        [rootLayer addSublayer:previewLayer];
        [session startRunning];
    
        //Orientation Code is in viewDidLayoutSubviews method
    }
    -(void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
        switch (orientation) {
            case UIInterfaceOrientationPortrait:
                [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
                break;
            case UIInterfaceOrientationPortraitUpsideDown:
                [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
                break;
            case UIInterfaceOrientationLandscapeLeft:
                [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
                break;
            case UIInterfaceOrientationLandscapeRight:
                [previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
                break;
            default:break;
        }
    }
    
  • 63

    @Maselko的回答是正确的,但有一点:您应该使用 UIApplication.shared.statusBarOrientation 而不是 UIDevice.current.orientation ,因为设备方向是您的设备定位的方式 . 当您的设备处于横向状态但您的UI不支持该方向时(例如,当我制作仅限风景的相机应用并在设备处于纵向位置时启动视图),它会中断 .

    private func updatePreviewLayer(layer: AVCaptureConnection, orientation: AVCaptureVideoOrientation) {
    
        layer.videoOrientation = orientation
    
        previewLayer.frame = self.view.bounds
    
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        if let connection =  self.previewLayer?.connection  {
    
            let currentDevice: UIDevice = UIDevice.current
    
            let orientation = UIApplication.shared.statusBarOrientation
    
            let previewLayerConnection : AVCaptureConnection = connection
    
            if previewLayerConnection.isVideoOrientationSupported {
    
                switch (orientation) {
                case .portrait: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
    
                    break
    
                case .landscapeRight: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeLeft)
    
                    break
    
                case .landscapeLeft: updatePreviewLayer(layer: previewLayerConnection, orientation: .landscapeRight)
    
                    break
    
                case .portraitUpsideDown: updatePreviewLayer(layer: previewLayerConnection, orientation: .portraitUpsideDown)
    
                    break
    
                default: updatePreviewLayer(layer: previewLayerConnection, orientation: .portrait)
    
                    break
                }
            }
        }
    }
    
  • 27

    这是我使用Swift 4的解决方案 .

    它很短,对我来说很漂亮 .

    open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
    
        let videoLayer = self.previewLayer
        coordinator.animate(alongsideTransition: { (context: UIViewControllerTransitionCoordinatorContext) in
    
            guard let connection = videoLayer?.connection, connection.isVideoOrientationSupported, let orientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue) else {
                return
            }
    
            connection.videoOrientation = orientation
            videoLayer?.frame = self.view.bounds
    
        }) { (context: UIViewControllerTransitionCoordinatorContext) in
            // handle any completion logic here...
        }
    }
    

相关问题