如何处理方向的变化,就像iPhone上的标准相机应用程序一样



我使用AVFoundation框架来访问相机。在标准相机应用程序中,当方向更改时,仅更改按钮上图标的旋转。但是当我尝试做类似的事情时,我遇到了与方向更改动画相关的问题。预览视图旋转,其后面的区域为黑色,并且在转动时有图像抖动。

现在我有这个代码:

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithFloat:duration]
                     forKey:kCATransactionAnimationDuration];
    if (toInterfaceOrientation==UIInterfaceOrientationLandscapeLeft){
        captureManager.previewLayer.transform=CATransform3DMakeRotation(M_PI/2, 0, 0, 1.0);
        captureManager.previewLayer.frame = CGRectMake(0, 0, 480, 320);
    } else if (toInterfaceOrientation==UIInterfaceOrientationPortrait){
        captureManager.previewLayer.transform=CATransform3DMakeRotation(0, 0, 0, 1.0);
        captureManager.previewLayer.frame = CGRectMake(0, 0, 320, 480);
    } else if (toInterfaceOrientation==UIInterfaceOrientationLandscapeRight){
        captureManager.previewLayer.transform=CATransform3DMakeRotation(M_PI+M_PI/2, 0, 0, 1.0);
        captureManager.previewLayer.frame = CGRectMake(0, 0, 480, 320);
    }
    [CATransaction commit];
}

我的想法是使用变换动画来处理旋转动画,但我遇到了滑行的问题。

如何创建相机预览视图并解决方向更改问题?可能我必须使用其他仪器才能使用相机?不是AVFoundation框架?

我知道我可以锁定方向并使用加速度计来处理按钮图标。但是我遇到了一些子视图控制器的问题。

对不起,英语不好。

您需要禁用控制器的横向,并通过处理方向更改通知来更新图标等的布局。在本主题中,它被描述正确 - 如何处理AVCaptureVideoPreviewLayer中的自动旋转?

Nikita 的答案有效,但需要额外的代码来处理设备旋转时 UI 元素的行为。如果这太麻烦了,另一个选项(我实现并工作)是有 2 个不同的 UIWindow 实例,一个用于相机的预览层,另一个用于要显示的 UI 元素。请注意,要使其正常工作,包含 UI 元素的窗口需要具有透明背景。

我通过以下方式处理预览旋转更改。

P.S 所有子视图在故事板上都设置了相应的约束,所以我只更新视频预览层的帧。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    DispatchQueue.main.async {
        self.videoPreviewLayer.frame = self.previewView.bounds
        self.setRotation()
    }
}

func setRotation() {
    let deviceOrientation = UIDevice.current.orientation
    switch deviceOrientation {
    case .landscapeLeft:
        videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.landscapeRight
        break
    case .landscapeRight:
        videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.landscapeLeft
        break
    case .portrait:
        videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portrait
        break
    case .portraitUpsideDown:
        videoPreviewLayer?.connection?.videoOrientation = AVCaptureVideoOrientation.portraitUpsideDown
        break
    default:
        break
    }
}

最新更新