防止AVCaptureVideoPreviewLayer旋转,但允许UI图层按方向旋转

yam*_*ski 5 avfoundation ios avcapturesession avcapturedevice

我有两个视图控制器.一个是根VC,包含UI界面,如记录按钮.在此视图控制器上,我还显示索引0处的另一个VC的视图.此视图包含AVCaptureVideoPreviewLayer.

我希望我的摄像机模仿苹果摄像机应用程序,界面布局随旋转调整,但视频预览层不会.您可以看到视频应用程序中的录制计时器(UILabel)如何消失,并根据方向重新出现在顶部.

知道怎么做吗?我发现了一个建议,建议将预览添加到app delegate的窗口,因为它不符合导航控制器的旋转,但它对我不起作用.

谢谢!

Eri*_*len 9

我有一个非常相似的情况.我只有一个视图控制器,我想要一个AVCaptureVideoPreviewLayer不旋转的视图控制器.我发现@ SeanLintern88接受的解决方案对我不起作用; 状态栏从未移动过,我在屏幕上看到的WKWebView没有正确调整大小.

我遇到的一个更大的问题是我把我AVCaptureVideoPreviewLayer放在了视图控制器的视图中.创建一个新的UIViewjust来保存图层要好得多.

之后我找到了Apple QA1890的技术说明:防止旋转视图.这让我可以生成以下快速代码:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)
{
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    coordinator.animateAlongsideTransition(
        { (UIViewControllerTransitionCoordinatorContext) in
            let deltaTransform = coordinator.targetTransform()
            let deltaAngle = atan2f(Float(deltaTransform.b), Float(deltaTransform.a))
            var currentRotation : Float = (self.previewView!.layer.valueForKeyPath("transform.rotation.z")?.floatValue)!
            // Adding a small value to the rotation angle forces the animation to occur in a the desired direction, preventing an issue where the view would appear to rotate 2PI radians during a rotation from LandscapeRight -> LandscapeLeft.
            currentRotation += -1 * deltaAngle + 0.0001;
            self.previewView!.layer.setValue(currentRotation, forKeyPath: "transform.rotation.z")
            self.previewView!.layer.frame = self.view.bounds
        },
        completion:
        { (UIViewControllerTransitionCoordinatorContext) in
            // Integralize the transform to undo the extra 0.0001 added to the rotation angle.
            var currentTransform : CGAffineTransform = self.previewView!.transform
            currentTransform.a = round(currentTransform.a)
            currentTransform.b = round(currentTransform.b)
            currentTransform.c = round(currentTransform.c)
            currentTransform.d = round(currentTransform.d)
            self.previewView!.transform = currentTransform
        })
}
Run Code Online (Sandbox Code Playgroud)

原始的技术说明没有线,self.previewView!.layer.frame = self.view.bounds但我发现非常必要,因为虽然锚点不移动,但框架有.如果没有该行,预览将被抵消.

此外,由于我正在完成将视图保持在正确位置的所有工作,因此我必须删除其上的所有定位约束.当我进入它们时,它们会导致预览反向偏移.


Sea*_*ern 6

确保将shouldAutorotate设置为return false:

-(BOOL)shouldAutorotate{
    return NO;
}
Run Code Online (Sandbox Code Playgroud)

注册方向更改的通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(orientationChanged:)
                                             name:UIDeviceOrientationDidChangeNotification
                                           object:nil];
Run Code Online (Sandbox Code Playgroud)

实施通知更改

-(void)orientationChanged:(NSNotification *)notif {
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];

// Calculate rotation angle
CGFloat angle;
switch (deviceOrientation) {
    case UIDeviceOrientationPortraitUpsideDown:
        angle = M_PI;
        break;
    case UIDeviceOrientationLandscapeLeft:
        angle = M_PI_2;
        break;
    case UIDeviceOrientationLandscapeRight:
        angle = - M_PI_2;
        break;
    default:
        angle = 0;
        break;
}


}
Run Code Online (Sandbox Code Playgroud)

并旋转UI

 [UIView animateWithDuration:.3 animations:^{
        self.closeButton.transform = CGAffineTransformMakeRotation(angle);
        self.gridButton.transform = CGAffineTransformMakeRotation(angle);
        self.flashButton.transform = CGAffineTransformMakeRotation(angle);
    } completion:^(BOOL finished) {

}];
Run Code Online (Sandbox Code Playgroud)

这是我实现屏幕被锁定但旋转UI的方式,如果这可以链接堆栈帖子,我可以将其复制到那里,你可以勾选它:P