info.plist 中支持的界面方向似乎阻止了对 shouldAutorotate 的调用



我正在设计一个iPad/iPhone应用程序,其中界面的设计在横向和纵向上看起来一样好,我希望界面在启动时在一个方向上像另一个方向一样优雅地出现。同时,我需要能够在不同时间启用/禁用自动旋转。我想我知道如何做这两件事,但它们似乎不能很好地结合在一起。

我可以在 Xcode 项目中设置允许的设备方向,这似乎在项目 info.plist 中创建几个数组项:"支持的界面方向 (iPad("和"支持的界面方向 (iPhone(",其中列出了每种类型设备的允许方向。这些物品的存在使启动屏幕的过渡在所有方向上都像丝绸一样平滑。

我可以通过在我的根视图控制器中覆盖 shouldAutorotate 来启用/禁用自动旋转(目前只有一个控制器(。问题在于 info.plist 中支持的接口项的存在似乎抑制了对 shouldAutorotate 的所有调用,从而使对自动旋转的控制不起作用。

class   RootController: UIViewController
{
var allowAutorotation = true    //  My autorotation switch.
{ didSet    { guard   allowAutorotation   else  { return }
UIViewController.attemptRotationToDeviceOrientation()
/*  Do other stuff.   */ }   }
override var supportedInterfaceOrientations: UIInterfaceOrientationMask
{ NSLog ("RootController: supportedInterfaceOrientations")
return .allButUpsideDown  }
override var shouldAutorotate: Bool
{ NSLog ("RootController: shouldAutorotate")
return allowAutorotation  }
override func viewDidLoad()
{ allowAutorotation = true
super.viewDidLoad()  }
}

我正在使用 viewDidLoad 在尽可能早的时刻调用 tryRotationToDeviceOrientation((。如果我不这样做,即使设备处于横向,应用程序屏幕也会以纵向显示。(它为"纵向"正确显示,但"纵向"不正确。我尝试从其他地方进行类似的调用,包括应用程序委托中的didFinishLaunchingWithOptions,我认为这可能是最合乎逻辑的地方,但它似乎没有区别。

如果我从 info.plist 中删除支持的方向项,并在代码中定义允许的方向,如下所示,我可以从我的 NSLog 提示中看到,对 shouldAutorotate 的调用确实在适当的时候发生,但启动在横向上看起来有点尴尬。在启动屏幕中,状态栏的方向错误:沿着其中一个垂直边缘而不是顶部,当过渡到应用程序屏幕时,它通常会在水平方向上倾斜约 10-20°。它立即捕捉到水平(事实上,它是如此之快,以至于有时很难看到(,然后状态栏正确位于顶部,从那一刻起,一切看起来都不错,但效果似乎仍然有点不专业。

由于它只暂时发生,而且只在启动时发生一次,我想我可以忍受它(没有自动旋转控件我就活不下去(,但我希望有人能提出一种方法让 shouldAutorotate 调用工作,即使有 info.plist 中定义的方向。或者也许是其他策略?

我想我有解决这些问题的方法。为了消除启动屏幕淡出时的异常旋转动画,我使用 CATransactions 禁用隐式动画,直到应用程序首次处于活动状态:

class RootController: UIViewController  {
private var appIsLaunching = true  //  Set false when app first becomes active. Never set true again.
func appDidBecomeActive()
{ if appIsLaunching  { appIsLaunching = false; CATransaction.setDisableActions (false) } } 
override func viewWillTransition (to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
{ if appIsLaunching  { CATransaction.setDisableActions (true) } 
super.viewWillTransition (to: size, with: coordinator) }
}

在应用程序中,委托:

func applicationDidBecomeActive ( _ application: UIApplication )
{ let root = window!.rootViewController as! RootController; root.appDidBecomeActive() }

我相信这是有效的,因为即使没有明确的事务,默认的 CATransaction 也始终有效。从启动屏幕到第一个视图的交叉溶解似乎很完美。

状态栏仍然以错误的方向显示在启动屏幕中。我得出的结论是,最好在项目设置中或通过设置状态栏最初隐藏在info.plist 中将其关闭。不理想,但可以接受。

最新更新