【发布时间】:2016-11-09 15:20:33
【问题描述】:
我想将所有 ViewControllers 中的方向锁定为纵向,除了其中一个,当它总是被推送到 LandscapeRight 时。
我尝试了很多解决方案,使用UINavigationController 的扩展,覆盖supportedInterfaceOrientations 和shouldAutorotate,但没有运气。
【问题讨论】:
标签: ios iphone swift screen-rotation
我想将所有 ViewControllers 中的方向锁定为纵向,除了其中一个,当它总是被推送到 LandscapeRight 时。
我尝试了很多解决方案,使用UINavigationController 的扩展,覆盖supportedInterfaceOrientations 和shouldAutorotate,但没有运气。
【问题讨论】:
标签: ios iphone swift screen-rotation
我找到了解决方案,目前它正在运行。
您应该在每个视图控制器上放置此代码以仅支持所需的旋转(示例中为landscapeRight):
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscapeRight
}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeRight
}
另一方面,实现相同的方法,但使用纵向。
为UINavigationController创建一个扩展
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return (self.topViewController?.supportedInterfaceOrientations)!
}
open override var shouldAutorotate: Bool {
return true
}
注意: 同样在项目的目标中启用所有需要的支持 方向。
我想在横向模式下以模态方式展示的唯一一个控制器。
【讨论】:
如果您使用导航控制器来呈现视图,您会感到困惑。例如,我们通常通过调用导航控制器实例函数如performSegueWithIdentifier:sender: 或pushViewController:animated: 来利用导航控制器来处理添加视图。
推送不会像你想要的那样工作。
segues 也可能不起作用,特别是如果在 IB 中您从导航控制器中创建了 segue!
无论如何,如果您以某种方式成功地覆盖了“父”导航控制器的方向,那么您可能会遇到边缘情况,并且您可能正在使用可能会因任何更新而失去支持的粗略东西。
也就是说,我找到的解决方法是:
第 1 步
使用presentViewController:animated:completion: 呈现landscapeRight 视图控制器:
// assuming you're using IB and Main bundle
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let landscapeViewController = storyboard.instantiateViewController(withIdentifier: "LandscapeViewControllerStoryboardID")
self.present(landscapeViewController, animated: true, completion: {
print("landscapeViewController presented")
})
第 2 步
将以下覆盖添加到您的 landscapeViewController 现在实际上有效:
/* override the preferredInterfaceOrientationForPresentation for a view controller
that is intended to be presented full screen in a specific orientation.
https://developer.apple.com/reference/uikit/uiviewcontroller */
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .landscapeRight
}
第 3 步(可选)
在所有这些工作之后,当您关闭 landscapeViewController 时仍然有些奇怪:它现在也是横向的。
这是因为导航控制器运行良好。换句话说,现在轮到导航控制器尝试强制改变方向,强制它回到原来的样子。
为此,您需要在present 和landscapeViewController 之前存储设备的方向。在您提供 landscapeViewController 的视图控制器中,我将它存储在一个实例变量中:
let ratio = self.view.bounds.width / self.view.bounds.height
if (ratio > 1) { // horizontal/landscape
self.currentOrientationIsPortrait = false // read by navigation controller when dismissing full screen view player
} else {
self.currentOrientationIsPortrait = true // read by navigation controller when dismissing full screen view player
}
然后,我在我的 navigationController 类的首选方向覆盖中测试该视图控制器实例的值。假设我从中呈现landscapeViewController 的视图控制器称为presentingViewController:
// execution order: during visibileViewController's dismissal
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
get {
if visibleViewController != nil {
// check if landscapeViewController is being dismissed
if (visibleViewController as? LandscapeViewController) != nil {
// check if the top view controller is one that tracks its orientation (currently only presentingViewController)
if let presentingViewController = self.viewControllers.last as? PresentingViewController {
if presentingViewController.currentOrientationIsPortrait {
return .portrait // TODO should we not support portraitUpsideDown?
}
}
}
// otherwise, return whatever
return visibleViewController!.preferredInterfaceOrientationForPresentation
}
// otherwise, return whatever
return super.preferredInterfaceOrientationForPresentation
}
}
还有,宾果游戏。 (希望)
编辑
另外别忘了把这段代码放到其他的ViewControllers中:
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return .portrait
}
【讨论】: