【问题标题】:Restoring Auto-Rotate after Forcing Orientation in Swift在 Swift 中强制定向后恢复自动旋转
【发布时间】:2015-09-20 14:48:09
【问题描述】:

在我的 iPhone 应用程序中,我有一个只想以纵向模式显示的视图。导航到该视图时,它应自动以纵向视图显示。导航离开时,方向应该变回原来的样子,或者,如果设备方向发生了变化,则适应它。我可以找到有关强制定向和防止自动旋转的信息。我找不到任何关于离开该视图后如何更改回正确方向的信息。

所以我的想法是

  1. 保存初始方向(存储在currentOrientation
  2. 订阅方向更改事件以在内容锁定为纵向时跟踪方向更改(更新currentOrientation
  3. 离开视图时,使用currentOrientation 值恢复正确的方向。

编辑(现已删除代码):除了无法正常工作之外,这是一种危险的做法,因为它大量使用了不受支持的 API。


编辑:

我相信这个问题现在可以归结为以下几点:

  1. 是否有文档化的、受支持的方式来强制界面方向独立于设备方向setValue(UIInterfaceOrientation.Portrait.rawValue, forKey: "orientation") 已在 SO 和其他地方多次推荐,但它确实似乎是不受支持的黑客攻击。

  2. 是否有文档化的、受支持的方法来将界面方向更新为设备方向?这将需要在另一个视图中从强制界面方向“恢复”,而无需通过来回转动设备来触发自动旋转。

支持supportedInterfaceOrientations()shouldAutorotate()。但是这些只会在设备转到该位置后锁定 interfaceOrientation。它们不能防止错误的初始方向。

类似这个问题的问题很多,说明这个问题设置并不少见,但目前使用支持的方法还没有令人满意的完整解决方案。

【问题讨论】:

  • 您为设置方向所做的操作未记录在案且不受支持。为这一视图添加横向支持可能比尝试控制旋转更容易。
  • 理想情况下,系统会在离开方向锁定视图后处理正确的方向,但它不会。有没有更简单的方法来实现这一点?创建该视图的横向版本不是一种选择。
  • 您应该删除 setValue(… forKey: "orientation") 位,因为它没有被记录和支持。您应该能够使用supportedInterfaceOrientations()shouldAutorotate()attemptRotationToDeviceOrientation() 实现您想要的。
  • 只是好奇(不要争论) - 为什么不创建视图的横向版本?我对您正在开发的用户体验感兴趣。
  • 谢谢,Aaron,我会多尝试一下,并尝试使用支持的接口提出一个更简单的解决方案。是的,不去景观是一个设计决定。这是一个跨平台应用程序,在 Windows 和 Android 中启动,该视图分别是中心页面或视图寻呼机。它有一个全屏背景图像,它几乎是应用程序的核心。即使我设法重新排列所有元素,它在水平视图中也不好看。完全重新设计该视图,例如使用标签时,我觉得该应用会丢失其(品牌)ID。

标签: ios swift uiinterfaceorientation uideviceorientation


【解决方案1】:

我有一个类似的问题,除了我需要一个视图控制器只在横向模式下工作,而另一个在纵向模式下工作。我实现这一点的方法是制作一个自定义的“根”视图控制器。然后在该控制器的viewWillTransitionToSize 方法上检查方向并且非动画地推动正确的视图控制器(因此它看起来像用户的旋转)。然后在 Interface Builder 中,我明确地设置了视图控制器的方向属性,而不是被推断出来。您可以通过仅在受限视图控制器上设置横向方向,然后在纵向旋转上什么都不做并在受限视图控制器上禁用自动旋转来应用此解决方案。

更新

我没有时间测试其中任何一个,但这些只是我在针对不同方向为不同 VC 实施我的解决方案时使用的想法,希望以下的一些组合可以工作我不能成为100% 肯定,因为我几个月前做过,但不完全记得什么有效,什么无效。

首先,确保您已按照屏幕截图所示设置了约束。我的有 iPad 全屏和横向,因为这就是我所做的将您的更改为您需要的任何内容(可以推断纵向和大小)。

现在在做任何其他事情之前,我会先检查一下这是否解决了问题。我需要根视图控制器,因为我需要一个用于纵向的不同 VC 和一个用于横向的不同 VC。你只需要限制它,如果它比那更完美,否则你可以尝试一些其他的事情,如下所述。

设置完成后,我将首先转到要限制其类并防止自动旋转的视图控制器:

 override func shouldAutorotate() -> Bool {
    return false
}

现在,如果您这样做,因为您仅限于纵向,我猜您并不真正关心颠倒,因此您不需要做任何额外的事情。如果您确实想使用viewWillTransitionToSize 方法并手动旋转。

如果仍然无法正常工作,您最终可以尝试使用根控制器的方式(但我会在最后一种情况下使用此方式)。这是它的草图:

class VC : UIViewController { 
      override func viewDidLoad () { 
           UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
           NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged:", name: "UIDeviceOrientationDidChangeNotification", object: nil)
         // this gives you access to notifications about rotations
      }
      func orientationChanged(sender: NSNotification)
      {
              // Here check the orientation using this:
              if UIInterfaceOrientationIsLandscape(UIApplication.sharedApplication().statusBarOrientation) { // Landscape }
              if UIInterfaceOrientationIsPortrait(UIApplication.sharedApplication().statusBarOrientation) { // Portrait }
           // Now once only allow the portrait one to go in that conditional part of the view. If you're using a navigation controller push the vc otherwise just use presentViewController:animated:
      }
}

我为 if 语句使用了不同的路径来相应地推送我想要的路径,但您可以手动推送肖像一个,希望上述方法之一对您有所帮助。

【讨论】:

  • 看起来很有希望,但我需要消化它。我是否正确理解您的解决方案仅导致横向视图(当然可以以相同的方式应用于纵向视图)?如果用户在设备处于不受支持的方向时导航到该视图会发生什么?在用户将设备转到支持的方向之前,它是否会卡在上一个视图上?
  • 不,如果用户是横向的,因为你只支持纵向,当用户导航到那个控制器时,视图将是纵向的,所以用户会意识到他们不能在那一点的风景。它有点像只支持横向的游戏,用户意识到他们必须旋转到横向,因为视图没有旋转,但在您的情况下,它只应用于应用程序的一部分。
  • 没有成功,但我不确定我是否完全理解你。如果时间允许,您能否简要地勾画一下根视图控制器的代码?
  • 感谢您的详细描述。不幸的是,它不起作用。首先,只有在加载根视图控制器时发生旋转事件时才会推送实际视图。之后,每次方向更改都会触发另一个主(受限)视图实例被推送到堆栈上,直到根视图控制器从堆栈中弹出。 shouldAutoRotate() 似乎没有任何效果。
  • 为了解决根视图控制器最初不推送的问题,只需调用viewDidAppear:animated中的orientationChanged函数即可。此外,为了防止多次推送,您需要存储当前方向,并且仅在方向更改时执行推送,我也忘了提到您必须 dismiss 视图控制器或弹出它,具体取决于您是否使用 UINavigationController .在没有动画的情况下执行所有这些操作,以便用户看不到它。
猜你喜欢
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-28
  • 1970-01-01
相关资源
最近更新 更多