只锁定一个 ViewController 的方向为横向,其余为纵向
Lock only one ViewController's orientation to landscape, and the remaining to portrait
我想将所有 ViewController 的方向锁定为纵向,但其中一个除外,当它被推送时始终处于 landscapeRight。
我尝试了很多解决方案,使用 UINavigationController
的扩展名,覆盖 supportedInterfaceOrientations
和 shouldAutorotate
但没有运气。
我找到了解决方案,目前有效。
在每个视图控制器上,您应该放置此代码以仅支持所需的旋转(示例中的 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 中创建了导航控制器之外的 segues!
无论如何,如果您以某种方式成功地覆盖了 "parent" 导航控制器的方向,您可能会 运行 冒着进入边缘情况的风险,并且您可能正在使用一些粗略的东西,可能会失去任何支持更新。
也就是说,我找到的解决方法是:
步骤 1
使用presentViewController:animated:completion:
呈现横向右视图控制器:
// 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 class' 首选方向覆盖中测试该视图控制器实例的值。假设我从中呈现 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
}
我想将所有 ViewController 的方向锁定为纵向,但其中一个除外,当它被推送时始终处于 landscapeRight。
我尝试了很多解决方案,使用 UINavigationController
的扩展名,覆盖 supportedInterfaceOrientations
和 shouldAutorotate
但没有运气。
我找到了解决方案,目前有效。
在每个视图控制器上,您应该放置此代码以仅支持所需的旋转(示例中的 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 中创建了导航控制器之外的 segues!
无论如何,如果您以某种方式成功地覆盖了 "parent" 导航控制器的方向,您可能会 运行 冒着进入边缘情况的风险,并且您可能正在使用一些粗略的东西,可能会失去任何支持更新。
也就是说,我找到的解决方法是:
步骤 1
使用presentViewController:animated:completion:
呈现横向右视图控制器:
// 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 class' 首选方向覆盖中测试该视图控制器实例的值。假设我从中呈现 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
}