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

我有两个视图控制器。 一个是根VC,包含录制button等UI界面。 在这个视图控制器上,我还显示另一个VC在索引0的视图。此视图包含一个AVCaptureVideoPreviewLayer。

我想我的摄像机模仿苹果video摄像头的应用程序,其中界面布局与旋转调整,但video预览层没有。 您可以看到股票video应用程序中的录制计时器(UILabel)如何消失,并根据方向重新显示在顶部。

任何想法如何做到这一点? 我发现一个build议,build议将预览添加到应用程序委托的窗口,因为它不符合导航控制器的旋转,但它不适用于我。

谢谢!

确保将shouldAutorotate设置为返回false:

-(BOOL)shouldAutorotate{ return NO; } 

注册方向已更改的通知:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil]; 

实施通知变更

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

并旋转UI

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

这是我如何实现屏幕locking,但旋转的UI,如果这个工程链接堆栈后,我可以在那里复制它,你可以打勾:P

我有一个非常相似的情况。 我只有一个视图控制器,我想有一个不会旋转的AVCaptureVideoPreviewLayer 。 我发现@ SeanLintern88接受的解决scheme不适合我; 状态栏永远不会移动,我在屏幕上的WKWebView没有正确resize。

我遇到的一个更大的问题是,我把AVCaptureVideoPreviewLayer放在视图控制器的视图中。 创build一个新的UIView只是为了保存图层更好。

之后,我从Apple QA1890发现技术说明:防止旋转视图 。 这使我能够产生下面的swift代码:

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

原来的技术笔记没有self.previewView!.layer.frame = self.view.bounds行,但我发现非常必要的,因为虽然锚点不移动,框架。 没有这一行,预览将被抵消。

而且,由于我正在做所有的工作,把视图保持在正确的位置,所以我不得不移除所有的定位约束。 当我有他们,他们会导致预览,而不是相反的方向偏移。

在显示相机输出的视图上添加:

 AVCaptureVideoPreviewLayer *layer = (AVCaptureVideoPreviewLayer *)self.layer; if ([layer.connection isVideoOrientationSupported]) { [layer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; } 

AVCaptureVideoOrientationPortrait只是一个选项。 您可以从以下选项中进行select:

 typedef NS_ENUM(NSInteger, AVCaptureVideoOrientation) { AVCaptureVideoOrientationPortrait = 1, AVCaptureVideoOrientationPortraitUpsideDown = 2, AVCaptureVideoOrientationLandscapeRight = 3, AVCaptureVideoOrientationLandscapeLeft = 4, } 

这必须安装会话完成。