简体   繁体   English

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

[英]How to change iOS status bar color in child view controller

(iOS 7 Xcode 5.0.2) (iOS 7 Xcode 5.0.2)

I used following methods, successfully change the status bar color to white on root view controller 我使用以下方法,在根视图控制器上成功将状态栏颜色更改为白色

[self setNeedsStatusBarAppearanceUpdate]; // Update status bar style

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

Now I'm trying to change status bar color to black when navigate to child view controller, I don't know how to do it.(status bar color is still white) 现在我试图在导航到子视图控制器时将状态栏颜色更改为黑色,但我不知道该怎么做。(状态栏颜色仍为白色)

I searched, and find this method: childViewControllerForStatusBarStyle I read Apple's document,But still don't know how to/where to use it, and I'm not sure if this is the right approach 我搜索了一下,找到了这种方法: childViewControllerForStatusBarStyle我阅读了苹果的文档,但仍然不知道如何/在哪里使用它,我不确定这是否是正确的方法

Anyone knows how to change status bar color in child view controller? 有人知道如何在子视图控制器中更改状态栏颜色吗?

By default, it seems that UINavigationController unfortunately doesn't provide a sensible default implementation of childViewControllerForStatusBarStyle . 默认情况下,似乎UINavigationController不能提供childViewControllerForStatusBarStyle的明智默认实现。 By implementing this method, you can tell your navigationController to defer all calls to preferredStatusBarStyle to its topmost childViewController. 通过实现此方法,可以告诉您的navigationController将对preferredStatusBarStyle所有调用推迟到其最顶层的childViewController。

You could either subclass UINavigationController and implement the method there, or simply add a category: 您可以子类化UINavigationController并在那里实现该方法,也可以简单地添加一个类别:

@implementation UINavigationController (ChildStatusBarStyle)

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

@end

I just find out: When you embed the root view controller inside UINavigationController correctly, You'd never need to create a category to expand the capability of navigation controller, or subclassing UINavigationController for the same purpose. 我发现:将根视图控制器正确地嵌入UINavigationController内时,无需创建类别来扩展导航控制器的功能,也无需出于同一目的而将UINavigationController子类化。

You just need to put preferredStatusBarStyle inside every view controller, and remember to call [self setNeedsStatusBarAppearanceUpdate]; 您只需要在每个视图控制器中放置preferredStatusBarStyle ,并记住要调用[self setNeedsStatusBarAppearanceUpdate]; to update status bar style. 更新状态栏样式。 Simple as it is! 就这么简单!

check out this video from WWDC 2013: Click Here 观看WWDC 2013的这段视频: 单击此处


EDIT: 编辑:

The reason I made it working, is I happen to set UINavigationBar hidden. 之所以使它起作用,是因为我碰巧将UINavigationBar设置为隐藏。 In this case, it behaves the same when not using UINavigationController at all. 在这种情况下,完全不使用UINavigationController时,其行为相同。 When you Trying to change StatusBarStyle of an UIViewController which is inside UINavigationController stack. 当您尝试更改位于UINavigationController堆栈内的UIViewController的StatusBarStyle时。 It will fail to work in this way. 它将无法以这种方式工作。 It only works in individual UIViewController. 它仅在单独的UIViewController中起作用。 The WWDC 2013 Video example is not using UINavigationController, so that why the approach is working fine. WWDC 2013 Video示例未使用UINavigationController,因此该方法运行良好。

James Frost answer was the only one that worked for me. James Frost的答案是唯一对我有用的答案。 Thank you! 谢谢! Here's a Swift 4 version of that code. 这是该代码的Swift 4版本。

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

Note: this is a bit unwieldy as-is, I recommend adding some code to limit its scope to a single viewController. 注意:这有点笨拙,我建议添加一些代码以将其范围限制为单个viewController。 Something like this: 像这样:

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

You'll obviously need to replace MyViewController with your UIViewController subclass that implements preferredStatusBarStyle. 显然,您将需要用实现PreferredStatusBarStyle的UIViewController子类替换MyViewController。

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

Again isBackgroundDark() is yours to implement. 同样,isBackgroundDark()是您要实现的。

Finally don't forget to call setNeedsStatusBarAppearanceUpdate() in your viewController every time isBackgroundDark() changes its value. 最后,每次isBackgroundDark()更改其值时,请不要忘记在viewController中调用setNeedsStatusBarAppearanceUpdate()。

In contrast to what James Frost said, and after much time spent debugging why my Browser Activities had wrong StatusBar colors (Swift): 与詹姆斯·弗罗斯特(James Frost)所说的相反,经过大量时间调试为什么我的浏览器活动具有错误的StatusBar颜色(快速):

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

That said: In some scenarios .topViewController is right, in others like with UIActivities it's .visibleViewController. 就是说:在某些情况下.topViewController是正确的,在其他情况下,例如UIActivities,它是.visibleViewController。

Thanks to @James Frost, the solution works well. 感谢@James Frost,该解决方案效果很好。
I didn't make it work at first, so I want to make a further explanation about it. 我一开始没有使其工作,所以我想对此做进一步的解释。

If you have a subclass of UINavigationController, it's important to add preferredStatusBarStyle in your UINavigationController subclass at the same time. 如果您有UINavigationController的子类,则必须在UINavigationController子类中同时添加preferredStatusBarStyle ,这一点很重要。

- (UIStatusBarStyle)preferredStatusBarStyle
{
  return UIStatusBarStyleLightContent;
}

And add childViewControllerForStatusBarStyle in extension of UINavigationController. 并在UINavigationController的扩展名中添加childViewControllerForStatusBarStyle

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

BTW, it's OK that UINavigationController subclass and extension of UINavigationController use different coding language, still work. 顺便说一句, UINavigationController子类和UINavigationController extension of UINavigationController使用不同的编码语言,这仍然可以。

I've tried another solutions and noticed that the Status Bar doesn't update without setNeedsStatusBarAppearanceUpdate() . 我尝试了另一种解决方案,并注意到没有setNeedsStatusBarAppearanceUpdate()不会更新状态栏。 There can be multiple places to call this marker, but the easies way is to override viewControllers setter. 可以在多个位置调用此标记,但是简便的方法是覆盖viewControllers setter。

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

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

Then you can use the StatusBarNavigationController programmatically or on a Storyboard. 然后,您可以以编程方式或在情节提要上使用StatusBarNavigationController

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM