Giz*_*odo 24 xcode uiviewcontroller landscape-portrait childviewcontroller swift
我想做什么:
由父视图控制器管理的父视图不应该旋转.
由子视图控制器管理的子视图应该旋转到所有方向.
我试过的:
ParentViewController
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Portrait
}
override func shouldAutorotate() -> Bool {
return true
}
fun addChildViewController() {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
self.childViewController = storyBoard("Child View Controller") as? ChildViewController
self .addChildViewController(self.childViewController!)
self.childViewController! .didMoveToParentViewController(self)
self.view .addSubview(self.childViewController!.view)
self.childViewController!.view.frame = CGRectMake (40, 200, 400, 250)
}
Run Code Online (Sandbox Code Playgroud)
ChildViewController
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .All
}
override func shouldAutorotate() -> Bool {
return true
}
Run Code Online (Sandbox Code Playgroud)
Xcode部署信息中支持的方向设置为全部四个.
我得到了什么:
没有View的旋转.如果我将父级的旋转设置为all,则所有视图一起旋转.所以它是全有或全无.
UPDATE
当我尝试把一个观察者UIDeviceOrientationDidChangeNotification和使用UIDevice.currentDevice()方向旋转childView使用CGAffaineTransformMakeRotate,我得到想要的结果.但是,如果我旋转到横向,并尝试拉下通知中心(或者如果我收到系统通知),仍然处于纵向(因为应用程序本身仍然保留在纵向中),旋转的childView会旋转回到肖像以表示状态栏/通知/通知中心.
股票iOS相机应用程序是我能呈现的最好的例子.主画布不会旋转到不同的方向,但状态栏在幕后旋转以表示设备旋转.子视图也在其自身内旋转以尊重不同的方向.我试图实现这种行为....
在相机应用程序中实现的效果类似于使用以下组合:
技术说明解释了autorotation的底层实现涉及将转换直接应用于应用程序的窗口:
当系统确定接口必须旋转时,通过将旋转变换应用于应用程序窗口来实现自动旋转.然后,窗口调整其新方向的边界,并通过调用每个视图控制器和表示控制器的
viewWillTransitionToSize:withTransitionCoordinator:方法将此更改向下传播到视图控制器层次结构中.
请注意,相机应用程序并不会退出自转:使用相机应用程序时,通知中心和控制中心的方向反映设备的方向.只有Camera应用程序中的特定视图才会选择退出自动旋转.事实上,这样的回答表明,这样的应用程序通常利用videoGravity和videoOrientation通过AVFoundation类,如提供的属性AVCaptureVideoPreviewLayer和AVCaptureConnection.
您应该采取的方法取决于您是否只想停止旋转父视图,或者是否要阻止容器视图控制器(如UINavigationController)旋转(即锁定设备方向).
如果是前者,请使用技术说明中描述的技术来修复父视图的方向,并且(对于iOS 9)在UIStackView中包装旋转子视图并使用该axis属性在设备旋转时重新排列子视图,或者(对于iOS 8) )手动旋转设备旋转上的子视图(如何查看此答案和此示例代码).
如果是后者,你所采取的方法是正确的.有关示例代码,请参阅此答案.您需要共享代码和有关视图控制器层次结构的更多信息,以便我们诊断涉及通知中心的怪癖.
附录:技术问答QA1688中解释了调用shouldAutorotate和supportedInterfaceOrientations未传播到子视图控制器的原因:
从iOS 6开始,只有最顶层的视图控制器(与
UIApplication对象一起)参与决定是否旋转以响应设备方向的更改.更多的,往往不是你的显示内容视图控制器是一个孩子UINavigationController,UITabBarController或自定义容器视图控制器.您可能会发现自己需要子类化容器视图控制器,以便修改其supportedInterfaceOrientations和shouldAutorotate方法返回的值.
在与 Apple 进行了多次来回交流之后,他们指向了相同的链接Technical Q&A QA1890,我不得不按照以下方式执行此操作:
母视图控制器
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
coordinator.animateAlongsideTransition({(context: UIViewControllerTransitionCoordinatorContext) -> Void in
let deltaTransform: CGAffineTransform = coordinator.targetTransform()
let deltaAngle: CGFloat = atan2(deltaTransform.b, deltaTransform.a)
var currentRotation: CGFloat = self.mainView.layer.valueForKeyPath("transform.rotation.z") as! CGFloat
// 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.mainView.layer.setValue(currentRotation, forKeyPath: "transform.rotation.z")
}, completion: {(
context: UIViewControllerTransitionCoordinatorContext) -> Void in
// Integralize the transform to undo the extra 0.0001 added to the rotation angle.
var currentTransform: CGAffineTransform = self.mainView.transform
currentTransform.a = round(currentTransform.a)
currentTransform.b = round(currentTransform.b)
currentTransform.c = round(currentTransform.c)
currentTransform.d = round(currentTransform.d)
self.mainView.transform = currentTransform
})
}
Run Code Online (Sandbox Code Playgroud)
主视图控制器
NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name:UIDeviceOrientationDidChangeNotification, object: nil)
func orientationChanged ( notification: NSNotification){
switch UIDevice.currentDevice().orientation {
case .Portrait:
self.rotateChildViewsForOrientation(0)
case .PortraitUpsideDown:
self.rotateChildViewsForOrientation(0)
case .LandscapeLeft:
self.rotateChildViewsForOrientation(90)
case .LandscapeRight:
self.rotateChildViewsForOrientation(-90)
default:
print ("Default")
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎在旋转子视图的同时保持主视图静态。此外,当通知进来时,应用程序似乎知道正确的方向(因为母视图实际上在幕后旋转)。
特别感谢jamesk和Warif Akhand Rishi提供的所有帮助!
| 归档时间: |
|
| 查看次数: |
5803 次 |
| 最近记录: |