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

问题描述 投票:9回答:6

(iOS 7 Xcode 5.0.2)

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

[self setNeedsStatusBarAppearanceUpdate]; // Update status bar style

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

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

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

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

ios objective-c cocoa-touch uiviewcontroller uistatusbar
6个回答
13
投票

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

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

@implementation UINavigationController (ChildStatusBarStyle)

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

@end

1
投票

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

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

看看WWDC 2013的这个视频:Click Here


编辑:

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


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
    }
}
}

您显然需要将MyViewController替换为实现preferredStatusBarStyle的UIViewController子类。

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

再次isBackgroundDark()是你的实现。

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


0
投票

与James Frost所说的相反,经过大量时间调试后,为什么我的浏览器活动有错误的StatusBar颜色(Swift):

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

这就是说:在某些情况下.topViewController是正确的,在其他情况下,与UIActivities一样,它是.visibleViewController。


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使用不同的编码语言是可以的,但仍然有用。


0
投票

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

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

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

然后,您可以通过编程方式或在故事板上使用StatusBarNavigationController

© www.soinside.com 2019 - 2024. All rights reserved.