如何在子视图控制器中更改iOS状态栏颜色

时间:2014-01-18 17:57:35

标签: ios objective-c cocoa-touch uiviewcontroller uistatusbar

(iOS 7 Xcode 5.0.2)

我使用了以下方法,在根视图控制器上成功将状态栏颜色更改为白色

[self setNeedsStatusBarAppearanceUpdate]; // Update status bar style

-(UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent; // Set status bar color to white
}

现在我试图在导航到子视图控制器时将状态栏颜色更改为黑色,我不知道该怎么做。(状态栏颜色仍为白色)

我搜索过,找到了这个方法: childViewControllerForStatusBarStyle 我读了Apple的文档,但仍然不知道如何/在哪里使用它,我不确定这是否是正确的方法

任何人都知道如何更改子视图控制器中的状态栏颜色?

6 个答案:

答案 0 :(得分:13)

默认情况下,UINavigationController似乎无法提供合理的childViewControllerForStatusBarStyle默认实现。通过实现此方法,您可以告诉您的navigationController将对preferredStatusBarStyle的所有调用推迟到其最顶层的childViewController。

你可以子类UINavigationController并在那里实现方法,或者只是添加一个类别:

@implementation UINavigationController (ChildStatusBarStyle)

- (UIViewController *)childViewControllerForStatusBarStyle 
{
    return self.topViewController;
}

@end

答案 1 :(得分:1)

我发现: 当您正确地在UINavigationController中嵌入根视图控制器时,您永远不需要创建一个类别来扩展导航控制器的功能,或者为了相同的目的将UINavigationController子类化。

您只需将preferredStatusBarStyle放在每个视图控制器中,并记得调用[self setNeedsStatusBarAppearanceUpdate];来更新状态栏样式。很简单!

查看WWDC 2013中的视频:Click Here


修改

我使其工作的原因是,我碰巧将UINavigationBar设置为隐藏。在这种情况下,它根本不使用UINavigationController时的行为相同。 当您尝试更改UINavigationController堆栈内的UIViewController的StatusBarStyle时。它将无法以这种方式工作。它只适用于单独的UIViewController。 WWDC 2013视频示例未使用UINavigationController,因此该方法工作正常。

答案 2 :(得分:1)

James Frost答案是唯一对我有用的答案。谢谢!这是该代码的Swift 4版本。

extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
    return topViewController
}
}

注意:这有点笨拙,我建议添加一些代码以将其范围限制为单个viewController。像这样:

extension UINavigationController {
override open var childViewControllerForStatusBarStyle: UIViewController? {
    if topViewController is MyViewController {
        return topViewController
    } else {
        return nil
    }
}
}

显然,您需要用实现PreferredStatusBarStyle的UIViewController子类替换MyViewController。

override var preferredStatusBarStyle: UIStatusBarStyle {
    if isBackgroundDark() {
        return .lightContent
    } else {
        return .default
    }
}

同样要实现isBackgroundDark()。

最后,不要忘记每次isBackgroundDark()更改其值时都在viewController中调用setNeedsStatusBarAppearanceUpdate()。

答案 3 :(得分:0)

与詹姆斯弗罗斯特所说的相反,经过大量时间调试,为什么我的浏览器活动有错误的StatusBar颜色(Swift):

override func childViewControllerForStatusBarStyle() -> UIViewController? {
    return visibleViewController
}

那说:在某些情况下.topViewController是对的,在其他情况下,比如UIActivities,它是.visibleViewController。

答案 4 :(得分:0)

由于@James Frost,该解决方案效果很好。
我一开始没有使其工作,所以我想对此做进一步的解释。

如果您有UINavigationController的子类, 重要的是要同时在您的UINavigationController子类中添加preferredStatusBarStyle

- (UIStatusBarStyle)preferredStatusBarStyle
{
  return UIStatusBarStyleLightContent;
}

并在UINavigationController扩展名中添加childViewControllerForStatusBarStyle

extension UINavigationController {
  override open var childViewControllerForStatusBarStyle: UIViewController? {
    return visibleViewController
  }
}

顺便说一句,UINavigationController子类和extension of UINavigationController使用不同的编码语言也是可以的。

答案 5 :(得分:0)

我尝试了另一种解决方案,但注意到没有setNeedsStatusBarAppearanceUpdate(),状态栏不会更新。可以在多个位置调用此标记,但是简便的方法是覆盖viewControllers设置器。

class StatusBarNavigationController: UINavigationController {
    override var childForStatusBarHidden: UIViewController? {
        return topViewController
    }

    override var viewControllers: [UIViewController] {
        didSet { setNeedsStatusBarAppearanceUpdate() }
    }
}

然后,您可以通过编程方式或在情节提要上使用StatusBarNavigationController