iOS:使用UIViewControllerBasedStatusBarAppearance YES

时间:2017-01-27 14:12:57

标签: ios uiappearance ios7-statusbar

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

这是问题所在,我正在处理:

几乎整个应用都需要使用UIStatusBarStyle.LightContent,因为导航栏背景较暗。最初,UIViewControllerBasedStatusBarAppearance已被停用,并且在Info.plist中为文本状态状态栏设置了以下内容:

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

这个工作正常,直到我发现这个.LightContent状态栏甚至显示为某些共享扩展名,例如Facebook Messenger,导致它不可读:

Facebook Messenger Share Extension light status bar style

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

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

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

2 个答案:

答案 0 :(得分:3)

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

一旦您开始进入基于特征收集的更改,大多数视图控制器所需的自定义转换动画,分析跟踪的中心点以及其他有用的东西,基本视图控制器也非常方便。

是的,您必须浏览可能较大的源代码库并将所有UIViewController更改为BaseViewController,但这通常与全局搜索和替换一样简单。

以下是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派生。然后,您不需要在需要它的每个视图控制器中复制状态条形码,并且您为所有&nbsp;功能保持良好的线性关系。

答案 1 :(得分:3)

解决方案

如何实现这一目标的最简单,最简洁的方法是在AppDelegate的{​​{1}}方法中添加以下行:

application:willFinishLaunchingWithOptions

只要您的应用使用UINavigationBar.appearance().barStyle = .Black ,这会将.LightContent作为默认状态栏样式通过应用。

如果要在启动闪屏期间使用UINavigationController状态栏样式,请不要忘记在应用的Info.plist中保留以下设置:

.LightContent

TL; DR

我当前的设置与许多其他应用非常相似,使用<key>UIStatusBarStyle</key> <string>UIStatusBarStyleLightContent</string> 作为最顶层的控制器,每个标签都有UITabBarController堆栈。

UINavigationController负责处理状态栏样式(应该如此),不要在其子视图控制器上调用UINavigationController。因此,在我的案例中,实施subclassing solution proposed by par并不起作用。

进一步继承preferredStatusBarStyle() I'm using的自定义子类也不是一个干净的解决方案。

现在,由于应用程序在应用程序本身的任何位置启用了UINavigationController并且状态栏样式正确,UIViewControllerBasedStatusBarAppearance和共享扩展名(如邮件,邮件等)使用正确的(SFSafariViewController)状态栏样式。

唯一不使用正确状态栏样式的例外是问讯中提到的F​​acebook Messenger的共享扩展。但是,它似乎是扩展本身的一个错误,因为我尝试使用.Default状态栏样式(例如Twitter)的所有应用程序都有相同的问题 - 从应用程序呈现的FB Messenger共享扩展程序有一个带有白色文本的状态栏。