iOS之StatusBar詳解

Goyakod發表於2017-12-17

隨便開啟手機上的主流APP,我們不難發現它們的狀態列都是跟導航欄保持一致的背景顏色,如下圖的微信和instagram:

WECHAT.PNG
INS.PNG
那麼今天我們就來說一下StatusBar這個只有區區20畫素高度的小東西。

#UIStatusBarStyle 狀態列有兩種顯示風格: 1.UIStatusBarStyleDefault

default.png

2.UIStatusBarStyleLightContent

lightContent.png

那麼它的背景顏色是怎麼加上去的呢?很簡單,看程式碼:

UIView *statusBar = [[UIView alloc] initWithFrame:CGRectMake(0, -20, self.view.frame.size.width, 20)];

statusBar.backgroundColor = myColor;

[self.navigationController.navigationBar addSubview:statusBar];
複製程式碼

看完程式碼就知道沒什麼可說的了。

要改變狀態列的顯示樣式(前景顏色)需要在ViewContoller裡過載方法:

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}
複製程式碼

但是上面這個方法不能直接呼叫,需要通過下面這個方法來重新整理狀態列的樣式,例如:


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    [self setNeedsStatusBarAppearanceUpdate];
}
複製程式碼

如果你按照上面說的,在自己的ViewController裡面設定一番之後,執行發現你的狀態列還是預設狀態...那就對了,因為遠沒有那麼容易。你還需要耐心往下看...

#UIViewControllerBasedStatusBarAppearance 在info.plist中可以設定狀態列的外觀是否是基於檢視控制器,鍵的名稱就是UIViewControllerBasedStatusBarAppearance,如果不設定那麼它的預設值是YES,表示檢視控制器決定了狀態列的風格;如果值設定為NO,則表示每個檢視控制器必須顯式地使用UIApplication物件來設定狀態列的風格。

哎~這個時候你肯定會疑惑了,我按照你上面說的沒有設定plist檔案啊,所以預設是YES,那麼就是由檢視控制器來決定狀態列風格啊,為什麼不對呢?

#childViewControllerForStatusBarStyle

當我們呼叫setNeedsStatusBarAppearanceUpdate時,系統會呼叫application.window.rootViewControllerpreferredStatusBarStyle方法,而不是當前控制器的preferredStatusBarStyle方法。在這個時候,一個重要的方法就要派上用場了,那就是:childViewControllerForStatusBarStyle

childViewControllerForStatusBarStyle預設返回nil。所以我們需要重寫這個方法。

假設你的APP里根檢視是導航控制器:

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:viewVontroller];
複製程式碼

那麼,我們子類化一個導航控制器ZXNavigationController,重寫它的childViewControllerForStatusBarStyle方法:

@implementation ZXNavigationController

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

- (void)viewDidLoad {
    [super viewDidLoad];
}
複製程式碼

上面程式碼的意思就是說,不要呼叫我自己也就是UINavigationController的preferredStatusBarStyle方法,而是去呼叫navigationController.topViewControllerpreferredStatusBarStyle方法,這樣寫的話,就能保證當前顯示的UIViewController的preferredStatusBarStyle方法能被呼叫,從而實現statusBar的前景顏色。

然後在application didFinishLaunchingWithOptions:方法裡把UINavigationController換成ZXNavigationController :

self.window.rootViewController = [[ZXNavigationController alloc] initWithRootViewController:viewVontroller];
複製程式碼

Run一下,就會發現:齊活兒了~

如果設定了UIViewControllerBasedStatusBarAppearanceNO;那麼就需要顯式地通過UIApplication物件來設定狀態列的風格:

self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:viewVontroller];
//setStatusBarStyle從9.0開始不被推薦使用了:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
複製程式碼

#最後 說了這麼多,簡單粗暴地概括下就是:如果想改變StatusBar的顯示風格,把UIViewControllerBasedStatusBarAppearance設定為NO,然後通過UIApplication物件設定StatusBar 的 Style。

Demo_Git地址

相關文章