仅锁定一个ViewController的横向方向,其余为纵向方向

时间:2016-11-09 15:20:33

标签: ios iphone swift screen-rotation

我希望将所有ViewControllers中的方向锁定为纵向,除了其中一个,当它始终被推送到landscapeRight时。 我尝试了很多解决方案,使用UINavigationController的扩展名,覆盖supportedInterfaceOrientationsshouldAutorotate,但没有运气。

2 个答案:

答案 0 :(得分:2)

我找到了解决方案,现在它正在运行。

  1. 在每个视图控制器上,您应该将此代码仅用于支持所需的旋转(示例中为landscapeRight):

    override var shouldAutorotate: Bool {
        return true
    }
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.landscapeRight
    }
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeRight
    }
    

    另一方面实现相同的方法但纵向方向。

  2. UINavigationController

    创建扩展程序
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return (self.topViewController?.supportedInterfaceOrientations)!
    }
    
    open override var shouldAutorotate: Bool {
        return true
    }
    
  3. 注意:同样在Project的目标中启用所有需要的支持 取向。

    我希望以横向模式显示的唯一一个控制器我以模态方式呈现。

答案 1 :(得分:1)

如果您使用导航控制器来呈现视图,您将会感到困惑。例如,我们通常通过调用performSegueWithIdentifier:sender:pushViewController:animated:等导航控制器实例函数来利用导航控制器来处理添加视图。

推送不会像你想要的那样起作用。

segues也可能不起作用,特别是如果在IB中你创建了离开导航控制器的segue!

无论如何,如果你以某种方式成功地覆盖了父母"导航控制器的方向,您可能会遇到边缘情况,您可能正在使用粗略的东西,可能会失去对任何更新的支持。

那就是说,我找到的解决方法是:

第1步

使用presentViewController:animated:completion:呈现landscapeRight视图控制器:

// 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时,仍然会有一些奇怪现象:它现在也是横向的。

这是因为导航控制器玩得很好。换句话说,现在导航控制器试图强制改变方向,强制它回到

要执行此操作,您需要在<{em> 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类中测试该视图控制器实例的值&#39;首选方向覆盖。让我们说我提出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
}