【问题标题】:UINavigationController: show embedded view controllers with different orientations after each transition?UINavigationController:每次转换后显示具有不同方向的嵌入式视图控制器?
【发布时间】:2017-01-02 20:48:17
【问题描述】:

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

以下是一些考虑的帖子:

我们在 UINavigationController 中嵌入了几个视图控制器:A、B、C、D。

A、B 使用纵向。

C、D 使用横向。

A 是根控制器。

假设 B 被推到 A 上。这是可行的,因为 B 是纵向的。但是,当 C 被推到 B 上时,屏幕不会旋转,因为正如类文档所述:

通常,系统仅在根视图上调用此方法 窗口的控制器或视图控制器,用于填充 整个屏幕;子视图控制器使用窗口的一部分 由他们的父视图控制器为他们提供,不再 直接参与有关支持哪些轮换的决策。

因此,在自定义 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 进入一个方向(使用公开支持的方法),一种可能的解决方案是在显示新视图控制器时强制该方向。但这似乎也不可能。

建议?

【问题讨论】:

    标签: ios swift uiviewcontroller uinavigationcontroller uikit


    【解决方案1】:

    步骤 1

    子类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 上的 TopBottom 标签是如何正确布局的。


    ↻ replay animation


    ► 在GitHub 上查找此解决方案,在Swift Recipes 上查找更多详细信息。

    【讨论】:

    • 我们在发布赏金后立即执行此操作,但会为您提供答案,但即使呈现,如果您将第二个 UINavigationController 保留为纵向,则会出现问题。这是要展示的代码:` let nc = storyboard!.instantiateViewController(withIdentifier: "NavigationControllerID2") as! UINavigationController 让 vc = nc.topViewController 一样! TestViewController vc.data = data present(nc, animated: true, completion: nil)`
    • 我明白了。我添加了一个指向 Swift 3 项目的链接供您试验。请注意,允许用户更改方向并预先强加方向可能会导致不可预知的后果。
    • 抱歉,自动更正。意味着“呈现”存在问题,而不是“甚至呈现”。你没有这个故障吗(第一次工作正常,但随后出现故障)?
    • 故障似乎与此错误有关:_BSMachError: port 7837; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND" 谷歌搜索和检查 SO 也没有产生有效的解决方案。
    • 你的意思是在日志中?还是视觉故障?使用我链接到的项目和 Storyboard segues 进行导航,没有什么。
    猜你喜欢
    • 2016-08-22
    • 1970-01-01
    • 2011-12-23
    • 2012-04-29
    • 1970-01-01
    • 2013-04-24
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多