UINavigationController:每次转换后显示具有不同方向的嵌入式视图控制器?

UINavigationController: show embedded view controllers with different orientations after each transition?(UINavigationController:每次转换后显示具有不同方向的嵌入式视图控制器?)
本文介绍了UINavigationController:每次转换后显示具有不同方向的嵌入式视图控制器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是 StackOverflow 上的常见问题,但其他解决方案均无效.许多也是几年前写的.

以下是一些考虑的帖子:

  • 为了更加方便,使用用户定义的运行时属性来控制LandscapeNavigationController的方向.

    第三步

    添加一个 pop 方法来处理现在模态 UIViewController 上的 Back 按钮.

    @IBAction func doBack(_ sender: UIBarButtonItem) {如果让导航控制器 = 导航控制器 {navigationController.dismiss(动画:真,完成:{})}}

    <小时>

    在行动

    注意视图 C 上的 TopBottom 标签是如何正确布局的.


    ↻ 重播动画

    <小时>

    ► 在 GitHub 上找到此解决方案,在 Swift 食谱.

    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?

    • How to force view controller orientation in iOS 8?

    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?

    解决方案

    Step1

    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 }}
    }
    

    Step2

    Use different UINavigationController for different orientations. Yes, pushing a new UINavigationController atop a previous UINavigationController will essentially be modal, but the transition looks nice.

    For added convenience, use User Defined Runtime Attributes to control the orientation of the LandscapeNavigationController.

    Step3

    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: {
            })
        }
    }
    


    InAction

    Notice how the Top and Bottom labels on view C are properly laid out.


    ↻ replay animation


    ► Find this solution on GitHub and additional details on Swift Recipes.

    这篇关于UINavigationController:每次转换后显示具有不同方向的嵌入式视图控制器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Why local notification is not firing for UNCalendarNotificationTrigger(为什么没有为UNCalendarNotificationTrigger触发本地通知)
iOS VoiceOver functionality changes with Bundle Identifier(IOS画外音功能随捆绑包标识符而变化)
tabbar middle tab out of tabbar corner(选项卡栏中间的选项卡角外)
Pushing UIViewController above UITabBar(将UIView控制器推送到UITabBar上方)
Dropbox Files.download does not start when number of files in folder is gt; 1000(当文件夹中的文件数为1000时,Dropbox Files.Download不会启动)
How can I sync two flatList scroll position in react native(如何在本机Reaction中同步两个平面列表滚动位置)