10

有没有办法在保持UIViewControllerBasedStatusBarAppearance启用状态的同时设置默认状态栏样式?

这是我正在处理的问题:

几乎整个应用程序都需要使用UIStatusBarStyle.LightContent,因为导航栏的背景是深色的。最初,UIViewControllerBasedStatusBarAppearance被禁用并在Info.plist文本状态栏中设置了以下内容:

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>

这工作得很好,直到我发现.LightContent即使对于某些共享扩展(如 Facebook Messenger)也会显示此状态栏,导致它不可读:

Facebook Messenger Share Extension 灯状态栏样式

这可以通过使用来解决UIViewControllerBasedStatusBarAppearance,但是我需要将以下方法添加到我想避免的所有视图控制器中,因为应用程序非常大。

此外,对于应用程序中具有浅色导航栏背景的一个屏幕,我使用的是切换到深色导航栏,UIApplication.sharedApplication().setStatusBarStyle()但这种方法在 iOS 9 中已弃用。

任何想法如何解决这个问题?嗖嗖嗖嗖?

4

2 回答 2

6

解决方案

AppDelegate实现这一目标的最简单和最简洁的方法是在's方法中添加以下行application:willFinishLaunchingWithOptions

UINavigationBar.appearance().barStyle = .Black

.LightContent只要您的应用使用UINavigationController.

Info.plist如果想.LightContent在启动时使用状态栏样式作为启动画面,请不要忘记在应用程序中保留以下设置:

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>

TL;博士

我当前的设置与许多其他应用程序非常相似,它UITabBarController用作最顶层的控制器,UINavigationController每个选项卡都有堆栈。

UINavigationController处理状态栏样式(应该如此)并且不调用preferredStatusBarStyle()其子视图控制器。因此,实施par 提出的子类化解决方案在我的情况下不起作用。

UINavigationController 进一步对我正在使用的自定义子类进行子类化也不是一个干净的解决方案。

现在,由于应用程序UIViewControllerBasedStatusBarAppearance在应用程序本身的任何地方都启用并正确的状态栏样式,SFSafariViewController并且消息、邮件等共享扩展程序也使用正确的 ( .Default) 状态栏样式。

未使用正确状态栏样式的唯一例外是问题中提到的 Facebook Messenger 的共享扩展。但是,这似乎是扩展程序本身的一个错误,因为我尝试过的所有使用.LightContent状态栏样式的应用程序(例如 Twitter)都有相同的问题 - 来自应用程序的 FB Messenger 共享扩展程序的状态栏为白色文本。

于 2017-02-05T15:12:10.337 回答
3

我经常使用的一个解决方案是创建一个基本视图控制器类,我的应用程序中的所有视图控制器都从该类派生。这具有允许使用具有默认(浅色或深色)样式的基于视图控制器的状态栏样式设置功能的优点,然后可以根据需要在每个视图控制器的基础上覆盖该样式。

一旦您开始了解基于 trait-collection 的更改、大多数视图控制器想要的自定义过渡动画、分析跟踪的中心点以及其他有用的东西,基本视图控制器也非常方便。

是的,您必须检查您可能很大的源代码库并将所有UIViewControllers 更改为BaseViewControllers,但这通常与全局搜索和替换一样简单。

以下是BaseViewController状态栏相关方法的外观:

class BaseViewController: UIViewController {
    var statusBarHidden: Bool = false { didSet { setNeedsStatusBarAppearanceUpdate() } }
    var statusBarStyle: UIStatusBarStyle = .lightContent { didSet { setNeedsStatusBarAppearanceUpdate() } }
    var statusBarUpdateAnimation: UIStatusBarAnimation = .fade { didSet { setNeedsStatusBarAppearanceUpdate() } }

    override var preferredStatusBarStyle: UIStatusBarStyle { return statusBarStyle }
    override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { return statusBarUpdateAnimation }
    override var prefersStatusBarHidden: Bool { return statusBarHidden }
}

对于所有使用默认灯光样式的视图控制器,你不需要做任何特别的事情:

class ViewController: BaseViewController { }

如果您需要深色状态栏,请执行以下操作:

class DarkStatusBarViewController: BaseViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        statusBarStyle = .default
    }
}

另请注意,您可以将DarkStatusBarViewController上述内容重命名为DarkStatusBarBaseViewController并从中派生,而不是BaseViewController在需要深色状态栏时。然后,您不需要在每个需要它的视图控制器中复制状态条码,并且您可以为所有BaseViewController功能保持良好的线性关系。

于 2017-01-29T21:37:59.733 回答