【问题标题】:Lock only one ViewController's orientation to landscape, and the remaining to portrait仅将一个 ViewController 的方向锁定为横向,其余为纵向
【发布时间】:2016-11-09 15:20:33
【问题描述】:

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

【问题讨论】:

    标签: ios iphone swift screen-rotation


    【解决方案1】:

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

    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
      }
      

    注意: 同样在项目的目标中启用所有需要的支持 方向。

    我想在横向模式下以模态方式展示的唯一一个控制器。

    【讨论】:

      【解决方案2】:

      如果您使用导航控制器来呈现视图,您会感到困惑。例如,我们通常通过调用导航控制器实例函数如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 时仍然有些奇怪:它现在也是横向的。

      这是因为导航控制器运行良好。换句话说,现在轮到导航控制器尝试强制改变方向,强制它回到原来的样子。

      为此,您需要在presentlandscapeViewController 之前存储设备的方向。在您提供 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 类的首选方向覆盖中测试该视图控制器实例的值。假设我从中呈现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
      }
      

      【讨论】:

      • 感谢您的努力。是的,这仅适用于一次编辑(编辑了答案)。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多