防止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, }
这必须在安装会话后完成。