iOS correctly sets the style of the status bar

White text status bar

Black text status bar

iOS status bar

Since iOS 7, iOS has adopted an immersive status bar design, and the status bar style is mainly black and white. For example, the two apps of Gift Talk and Jiaxue (disbanded) adopt these two different designs.

Generally speaking, a dark background navigation bar will match a white status bar, and a light background navigation bar will match a dark status bar.

Before iOS 9, we generally UIViewControllerBasedStatusBarAppearanceset the key to NO in the project info.plist file ,

UIViewControllerBasedStatusBarAppearance

Then use the following code in the appropriate view controller to set the status bar style:


 
  
  
  1. /// Set the white status bar
  2. [[ UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleLightContent];
  3. /// Set the black status bar
  4. [[ UIApplication sharedApplication] setStatusBarStyle: UIStatusBarStyleDefault];

However, this code structure disrupts the rhythm of our status bar control. Imagine that if the status of the status bar in the project changes very frequently, you have to update and restore the style state of the status bar under various ViewControllers. In fact, all we need is to associate each ViewController with the corresponding StatusBarStyle. We don't need global modification, global means chaos.

Therefore, the above method will cause a warning after iOS 9 (Xcode 7). Apple no longer recommends using the old method. We need to override the view controller +preferredStatusBarStylemethod to set the status bar style:


 
  
  
  1. // Setting the statusBarStyle does nothing if your application is using the default UIViewController-based status bar system.
  2. @available(iOS, introduced= 2.0, deprecated= 9.0, message= "Use -[UIViewController preferredStatusBarStyle]")
  3. public var statusBarStyle: UIStatusBarStyle
  4. @available (iOS, introduced= 2.0 , deprecated= 9.0 , message= "Use -[UIViewController preferredStatusBarStyle]" )
  5. public func setStatusBarStyle(statusBarStyle: UIStatusBarStyle, animated: Bool)

So quickly set the UIViewControllerBasedStatusBarAppearancekey in the project info.plist file to NO (or delete), and don't forget to setStatusBarStyledelete the items in your project as well. Here will show you how to set the style of the status bar elegantly.


Case 1: Single view application

Create a new Single view application project, set the background color of the view controller to aqua blue, and rewrite the preferredStatusBarStyleproperties.


 
  
  
  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. self.view.backgroundColor = UIColor . init(colorLiteralRed: 0.157, green: 0.694, blue: 1, alpha: 1)
  4. }
  5. override var preferredStatusBarStyle: UIStatusBarStyle {
  6. return .lightContent
  7. }

White status bar

The effect looks good?.

Case 2: View controller embed in a navigation controller

But if my View Controller is in a navigation stack, the status bar turns black again:

View controller embed in a navigation controller

 

The status bar is black again


Let's take a look at preferredStatusBarStyle()the definition:

 


 
  
  
  1. // These methods control the attributes of the status bar when this view controller is shown. They can be overridden in view controller subclasses to return the desired status bar attributes.
  2. @available(iOS 7.0, *)
  3. open var preferredStatusBarStyle: UIStatusBarStyle { get } // Defaults to UIStatusBarStyleDefault

The main idea is that this property can be used to control the properties of the status bar when the view controller is displayed. You can override this calculated property in a subclass of UIViewController to return the status bar properties you expect.

So why does it not work if I reload this attribute now? It is preferredStatusBarStyle()not actually called. Because the current view controller is located in a container class controller. The container controller includes UINavigationVontroller, UITabBarControlleretc. In this case, the style of the status bar will be managed by the container, you only need to reload and change the attributes in the container controller. (The code in the figure below is Swift 2)

Overload the preferredStatusBarStyle() method in NavigationController

Correct result

Case3: Switch style

We may encounter such a requirement that the status bar in the first view controller in the navigation stack is white, and the status bar in the second view controller is black. The above method of controlling the properties of the status bar in the navigation bar controller obviously does not meet our requirements. Fortunately, the iOS SDK provides us with another property:


 
  
  
  1. // Override to return a child view controller or nil. If non-nil, that view controller's status bar appearance attributes will be used. If nil, self is used. Whenever the return values from these methods change, -setNeedsUpdatedStatusBarAttributes should be called.
  2. @available(iOS 7.0, *)
  3. open var childViewControllerForStatusBarStyle: UIViewController? { get }

The general idea is that if the return value of this method is non-nil, the control right to change the properties of the status bar will be transferred to the controller you returned. If the return value is nil or the method is not overloaded, then you are responsible for controlling the properties of the status bar. Whenever the style of the status bar is changed, you should call the controller -setNeedsUpdatedStatusBarAttributesmethod. The last sentence says that if you want to change the style of the status bar from time to time on the current page, then you need to call the -setNeedsStatusBarAppearanceUpdatemethod first (it informs the system to reacquire the current UIViewController preferredStatusBarStyle).

To achieve our needs, we can NavigationControlleroverload the -childViewControllerForStatusBarStyleproperties in, since it returns an instance of the view controller, then we only need to use the navigation stack topViewControlleras the return value (this method will be called multiple times, and each time ~~ set the state Bar style ~~push/pop view controller (this method will be called), and then reload the preferredStatusBarStyleproperties in the controller where you need to set the status bar style as at the beginning .


 
  
  
  1. override var childViewControllerForStatusBarStyle: UIViewController? {
  2. return self.topViewController
  3. }

final effect

Case4: Present Modal Controller

It should be pointed out that if a view controller is presented, usually the view controller ignores preferredStatusBarStyleattributes, and you need to set such an attribute before it is presented:

vc.modalPresentationCapturesStatusBarAppearance = true

 
  
  

 
  
  
  1. // This controls whether this view controller takes over control of the status bar's appearance when presented non-full screen on another view controller. Defaults to NO.
  2. @available(iOS 7.0, *)
  3. open var modalPresentationCapturesStatusBarAppearance: Bool



Author: waylen
link: https: //www.jianshu.com/p/0d4337b2e18a
Source: Jane book
Jane book copyright reserved by the authors, are reproduced in any form, please contact the author to obtain authorization and indicate the source.

Guess you like

Origin blog.csdn.net/Draven__/article/details/90759054