UINavigationController:在每次转换后显示具有不同方向的嵌入式视图控制器? [英] UINavigationController: show embedded view controllers with different orientations after each transition?
问题描述
这是StackOverflow上的一个常见问题,但其他解决方案都没有奏效。许多人也在几年前写过。
以下是一些考虑的帖子:
-
为了方便起见,请使用用户定义运行时属性控制
LandscapeNavigationController的方向
。
第3步
添加 pop 方法来处理现在莫代尔
UIViewController
上的返回按钮。@ IBAction func doBack(_ sender:UIBarButtonItem){
if let navigationController = navigationController {
naviga tionController.dismiss(animated:true,completion:{
})
}
}
在行动中
注意顶部和底部如何视图 C 上的标签已正确布局。
►在 GitHub 上查找此解决方案有关 Swift Recipes 的详细信息。
This is a common question on StackOverflow, but none of the other solutions worked. Many were also written several years ago.
Here are some of the posts considered:
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?
We have several view controllers embedded inside a UINavigationController: A, B, C, D.
A, B use portrait.
C, D use landscape.
A is the root controller.
Assume B gets pushed onto A. That works since B is portrait. However, when C gets pushed onto B, the screen doesn't rotate since as the class docs state:
Typically, the system calls this method only on the root view controller of the window or a view controller presented to fill the entire screen; child view controllers use the portion of the window provided for them by their parent view controller and no longer participate directly in decisions about what rotations are supported.
So overriding
supportedInterfaceOrientations
inside a custom UINavigationController doesn't help because it isn't consulted on transitions within embedded controllers.Effectively, we need a way to force orientation changes upon transitions, but there seems to be no supported method for this.
Here's how we override UINavigationController (extension is only used now for debugging purposes since apparently extensions shouldn't be used for overriding):
extension UINavigationController { override open var shouldAutorotate: Bool { return true } override open var supportedInterfaceOrientations : UIInterfaceOrientationMask { return visibleViewController?.supportedInterfaceOrientations ?? UIInterfaceOrientationMask.landscapeRight } }
Within embedded view controllers, we try to set the orientation like this:
override var shouldAutorotate: Bool { return true } override var preferredInterfaceOrientationForPresentation : UIInterfaceOrientation { return UIInterfaceOrientation.landscapeRight } override var supportedInterfaceOrientations : UIInterfaceOrientationMask { return UIInterfaceOrientationMask.landscapeRight }
To summarize, the goals are:
1) Show view controllers embedded inside a UINavigationController with different orientations.
2) VC transitions should yield proper orientation change (e.g., popping from C->B should yield portrait, popping from D->C should yield landscape, pushing from B->C should yield landscape, pushing from A->B should yield portrait).
If it were possible to force the UINavigationController into an orientation (with publicly supported method), one possible solution could be to force the orientation upon showing the new view controller. But this also doesn't seem possible.
Suggestions?
解决方案Step 1
Subclass
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 }} }
Step 2
Use different
UINavigationController
for different orientations. Yes, pushing a newUINavigationController
atop a previousUINavigationController
will essentially be modal, but the transition looks nice.For added convenience, use User Defined Runtime Attributes to control the orientation of the
LandscapeNavigationController
.Step 3
Add a pop method to handle Back buttons on the now modal
UIViewController
.@IBAction func doBack(_ sender: UIBarButtonItem) { if let navigationController = navigationController { navigationController.dismiss(animated: true, completion: { }) } }
In Action
Notice how the Top and Bottom labels on view C are properly laid out.
► Find this solution on GitHub and additional details on Swift Recipes.
这篇关于UINavigationController:在每次转换后显示具有不同方向的嵌入式视图控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!