这是StackOverflow上的一个常见问题,但其他解决方案都没有奏效。许多人也在几年前写过。
以下是一些考虑的帖子:
Is it possible to have different orientations for viewControllers inside UINavigationController?
Support landscape for only one view in UINavigationController
Is it possible to have different orientations for viewControllers inside UINavigationController?
Why can't I force landscape orientation when use UINavigationController?
我们在UINavigationController中嵌入了几个视图控制器:A,B,C,D。
A,B使用肖像。
C,D使用风景。
A是根控制器。
假设B被推到A.这是有效的,因为B是肖像。但是,当C被推到B上时,屏幕不会旋转,因为类docs状态:
通常,系统仅在根视图上调用此方法 窗口的控制器或视图控制器呈现填充 整个屏幕;子视图控制器使用窗口的一部分 由他们的父视图控制器提供给他们,不再 直接参与有关支持轮换的决定。
因此在自定义UINavigationController中覆盖supportedInterfaceOrientations
没有帮助,因为在嵌入式控制器中的转换时不会参考它。
实际上,我们需要一种在转换时强制方向更改的方法,但似乎没有支持这种方法。
以下是我们如何覆盖UINavigationController(扩展现在仅用于调试目的,因为显然扩展不应该用于覆盖):
extension UINavigationController {
override open var shouldAutorotate: Bool {
return true
}
override open var supportedInterfaceOrientations : UIInterfaceOrientationMask {
return visibleViewController?.supportedInterfaceOrientations ?? UIInterfaceOrientationMask.landscapeRight
}
}
在嵌入式视图控制器中,我们尝试设置这样的方向:
override var shouldAutorotate: Bool {
return true
}
override var preferredInterfaceOrientationForPresentation : UIInterfaceOrientation {
return UIInterfaceOrientation.landscapeRight
}
override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscapeRight
}
总结一下,目标是:
1)显示嵌入在具有不同方向的UINavigationController内的视图控制器。
2)VC转换应该产生适当的方向改变(例如,从C-弹出B应该产生肖像,从D-弹出C应该产生风景,从B-推动C>应该产生风景,推动A-> B应该产生肖像。)如果可以强制UINavigationController进入方向(使用公开支持的方法),一种可能的解决方案可能是在显示新视图控制器时强制方向。但这似乎也不可能。
建议?
答案 0 :(得分:4)
子类UINavigationController
。
class LandscapeNavigationController: UINavigationController {
public var vertical: Bool = true
override var shouldAutorotate: Bool {
get { return true }}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
get { return (vertical) ? .portrait : .landscapeLeft }}
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
get { return (vertical) ? .portrait : .landscapeLeft }}
}
对不同的方向使用不同的UINavigationController
。是的,在之前的UINavigationController
上推一个新的UINavigationController
基本上是模态的,但过渡看起来不错。
为了方便起见,请使用用户定义的运行时属性来控制LandscapeNavigationController
的方向。
添加 pop 方法来处理现在模态UIViewController
上的 Back 按钮。
@IBAction func doBack(_ sender: UIBarButtonItem) {
if let navigationController = navigationController {
navigationController.dismiss(animated: true, completion: {
})
}
}
请注意视图 C 上的顶部和底部标签是如何正确布局的。
►在GitHub上找到此解决方案,并在Swift Recipes上找到其他详细信息。