我有一个嵌入在标签栏控制器中的视图控制器,除其他功能外,它还可以在UIView中呈现AVCaptureVideoPreviewLayer。
旋转设备时,我希望视图控制器随其旋转-除了上述UIView。
但是,与this related question不同,我不只是在视图控制器中旋转/变换其他视图。其他视图需要使用其配置的自动布局旋转行为。
我尝试了几件事,包括简单地将视频方向设置为纵向:
previewLayer.connection.videoOrientation = .portrait
将UIView提取到单独的视图控制器,将该视图控制器嵌入到原始视图控制器中,并设置其autoRotation属性
override var shouldAutorotate: Bool {
return false
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
但是后来我了解到here,iOS仅查看这些属性的顶级视图控制器。
使用我尝试过的所有方法,视频预览都与视图控制器的其余部分一起旋转-侧向结束。
这是唯一可行的方法,但是它很笨拙,有时会导致视频预览无法对齐
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if let videoPreviewLayerConnection = previewLayer.connection {
if let newVideoOrientation = AVCaptureVideoOrientation(rawValue: UIApplication.shared.statusBarOrientation.rawValue) {
videoPreviewLayerConnection.videoOrientation = newVideoOrientation
}
}
}
}
我基本上需要与this question相反。
如何强制视频预览不旋转,但又允许视图控制器的其余部分正常旋转?(与iOS Camera应用程序的行为相同,只是其他UI元素正常旋转而不是旋转90°旋转变换)
答案 0 :(得分:0)
以下内容可能与您的解决方案一样棘手,但外观看上去更清晰。
在viewWillTransition
中,我设置了PreviewView的仿射变换,以抵消通过旋转手机设置的方向。它看起来比仅设置videoOrientation更为干净,因为仿射变换的动画制作速度与方向变化相同。操作如下。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
let orientation = UIDevice.current.orientation
var rotation : CGFloat = self.previewView.transform.rotation
switch(orientation) {
case .portrait:
rotation = 0.0
case .portraitUpsideDown:
rotation = CGFloat.pi
case .landscapeLeft:
rotation = -CGFloat.pi/2.0
case .landscapeRight:
rotation = CGFloat.pi/2.0
default:
break
}
let xScale = self.previewView.transform.xScale
let yScale = self.previewView.transform.yScale
self.previewView.transform = CGAffineTransform(scaleX:xScale, y:yScale).rotated(by:rotation)
self.view.layoutIfNeeded()
}
这是CGAffineTransform上面代码使用的扩展
extension CGAffineTransform {
public var xScale: CGFloat {
get {return sqrt(self.a * self.a + self.c * self.c) }
}
public var yScale: CGFloat {
get {return sqrt(self.b * self.b + self.d * self.d) }
}
public var rotation: CGFloat {
get {return CGFloat(atan2f(Float(self.b), Float(self.a))) }
}
}