The correct way to set a light status bar text col

2019-02-03 06:37发布

问题:

I need to let a specific ViewController embedded in an UINavigationController to have light status bar text color (but other ViewControllers to behave differently). I am aware of at least 3 methods, none of which however work in my case.

  1. How to change Status Bar text color in iOS 7, the method is primarily:

    • Set the UIViewControllerBasedStatusBarAppearance to YES in the plist
    • In viewDidLoad do a [self setNeedsStatusBarAppearanceUpdate];
    • Add the following method:

      - (UIStatusBarStyle)preferredStatusBarStyle{ 
            return UIStatusBarStyleLightContent; 
        }
      

    Running on iOS 7.0.3, this method does not work for me, since even after I have implemented all 3 steps correctly, preferredStatusBarStyle is never called.

  2. UIStatusBarStyle PreferredStatusBarStyle does not work on iOS 7, the method is primarily:

    Setting your navigationBar’s barStyle to UIBarStyleBlackTranslucent will give white status bar text (ie. UIStatusBarStyleLightContent), and UIBarStyleDefault will give black status bar text (ie. UIStatusBarStyleDefault).

    This method works fair and square on iPhone, but not on iPad.

  3. Setting the UIViewControllerBasedStatusBarAppearance to NO in the plist, and use

    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
    

    This clearly doesn't apply in this case, since I need to only specify different status bar colors for two of the ViewControllers.

Thanks for all help!

回答1:

For people having this problem with a UINavigationController I can recommend creating a custom UINavigationController and implementing the preferredStatusBarStyle on it like this:

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return [self.topViewController preferredStatusBarStyle];
}

That way the statusbar style will be that of the top view controller. Now you can implement the view controller's preferredStatusBarStyle anyway you like.



回答2:

Here's an improvement to Groot answer, in form of a simple category to UINavigationController, without the need to subclass UINavigationController.

Swift

extension UINavigationController {
    override public func preferredStatusBarStyle() -> UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle() ?? .Default
    }
}

Swift 3 & Swift 4

extension UINavigationController {
    open override var preferredStatusBarStyle: UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? .default
    }
}

Objective-C

@implementation UINavigationController (StatusBarStyle)

- (UIStatusBarStyle)preferredStatusBarStyle 
{
    return [self.topViewController preferredStatusBarStyle];
}

@end


回答3:

To set UIStatusBarStyle individually for each UIViewController on UINavigationController stack you have to first subclass your UINavigationController and override childViewControllerForStatusBarStyle method.

In your UINavigationController subclass add:

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

than you can set UIStatusBarStyle to whatever you want in every UIViewController using preferredStatusBarStyle method. Eg:

-(UIStatusBarStyle)preferredStatusBarStyle {
     return UIStatusBarStyleLightContent;
}


回答4:

I used the first method you mentioned, I also found there's kinda bug when you used UINavigationController, it will never pass preferredStatusBarStyle call to it's child view controllers. What I have done is subclass the UINavigationController, and override preferredStatusBarStyle method as follows:

@implementation GLBaseNavigationController

- (UIStatusBarStyle)preferredStatusBarStyle
{
    UIViewController *lastViewController = [self.viewControllers lastObject];
    if ([lastViewController respondsToSelector:@selector(preferredStatusBarStyle)]) {
        return [lastViewController preferredStatusBarStyle];
    } else if ([super respondsToSelector:@selector(preferredStatusBarStyle)]) {
        return [super preferredStatusBarStyle];
    }
    return UIStatusBarStyleDefault;
}

Then whenever I need a navigation controller, I use GLBaseNavigationController instead of UINavigationController. For storyboards, you need to specify the class of the navigation controller to your subclass as well.



回答5:

For your first solution, I don't think you can change the status bar in viewDidLoad. If you have two ViewControllers stacked on top of each other, and each one toggles the status bar differently, that method will only get called once for each. You really want to change the status bar in viewWillAppear so that it gets called each time the page is shown. I also don't think you can rely on preferredStatusBarStyle since I'm also not sure how often/when that gets called. This is how you want to do it:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar setBarStyle:UIBarStyleDefault];
}


回答6:

Currently you can only do light and dark. To change to light do.

  1. Set the UIViewControllerBasedStatusBarAppearance to YES in the .plist file.

  2. In the viewDidLoad method do [self setNeedsStatusBarAppearanceUpdate];

  3. Add the this method:

-(UIStatusBarStyle)preferredStatusBarStyle{ return UIStatusBarStyleLightContent; }

To change it back to dark change the UIStatusBarStyleLightContent to UIStatusBarStyleDefault



回答7:

In your AppDelegate didFinishLaunch method, set the default status bar style, say:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault
                                                animated:YES];       
    return YES;
}

Then, in your those two view controllers, where you want to change status bar, override following methods:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated]        

    // Here change status bar color
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent
                                                animated:YES];       

}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear]                

    // Here bring back to color, that we set in AppDelegate
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault
                                                animated:YES];       
}