自定義狀态欄
有時候,需要在狀态欄上顯示一些自定義資訊,比如新浪微網誌的官方iOS用戶端:告知使用者資訊處于發送隊列、發送成功或者發送失敗。

如上圖,通過在狀态欄顯示自定義資訊,可以給使用者友好又不影響軟體使用的提示。
為此,我們顯得定義一個自定義狀态欄類,包含一個顯示資訊的Label:
@interface CustomStatusBar : UIWindow
{
UILabel *_messageLabel;
}
- (void)showStatusMessage:(NSString *)message;
- (void)hide;
@end
接着,設定大小和系統狀态欄一緻,背景為黑色:
self.frame = [UIApplication sharedApplication].statusBarFrame;
self.backgroundColor = [UIColor blackColor];
到這裡,為了讓自定義的狀态欄可以讓使用者看到,還需要設定它的windowLevel。
在iOS中,windowLevel屬性決定了UIWindow的顯示層次。預設的windowLevel為UIWindowLevelNormal,即0.0。
系統定義了三個層次如下,
const UIWindowLevel UIWindowLevelNormal;
const UIWindowLevel UIWindowLevelAlert;
const UIWindowLevel UIWindowLevelStatusBar;
typedef CGFloat UIWindowLevel;
為了能夠覆寫系統預設的狀态欄,我們把自定義的狀态欄的windowLevel調高點:
self.windowLevel = UIWindowLevelStatusBar + 1.0f;
隐藏狀态欄
如果想要隐藏狀态欄,有兩種做法:
狀态欄是否隐藏預設由控制器管理,也就是說,目前狀态欄所對應的控制器決定是否隐藏狀态欄。
UIViewController中提供了一個prefersStatusBarHidden方法用于檢視目前的控制器顯示的狀态欄是否隐藏,預設這個方法傳回的是NO,也就是不隐藏。但是并沒有提供相應的方法來設定隐藏狀态欄。
這種情況我們可以重寫prefersStatusBarHidden方法,通過修改它的傳回值達到目的。
- (BOOL)prefersStatusBarHidden
{
return YES;
}
這樣狀态欄就可以隐藏了。
另一種做法是不讓控制器來決定是否隐藏狀态欄,而是讓[UIApplication sharedApplication]來決定。
[UIApplication sharedApplication].statusBarHidden = YES;
運作程式發現狀态欄并沒有隐藏。檢視文檔可以發現:
Setting statusBarHidden does nothing if your application is using the default UIViewController-based status bar system.
意思是如果使用預設的控制器管理狀态欄(第一種做法提到的),那麼設定statusBarHidden是沒有效果的。想要關閉控制器的管理,需要我們給Info.plist增加一個key:
View controller-based status bar appearance
并且設定為NO,這樣就可以通過設定statusBarHidden來隐藏狀态欄了。(這個key是Info.plist添加Key出現的下拉欄裡的最後一個)
當控制器管理狀态欄時
- (UIViewController *)childViewControllerForStatusBarHidden
- (UIViewController *)childViewControllerForStatusBarStyle
這兩個方法可以将狀态欄的控制權交給子控制器管理,如果傳回nil則表示控制器自己來管理狀态欄;如果傳回子控制器,則表示子控制器來管理狀态欄。比如在navigation controller中實作prefersStatusBarHidden方法可能并不管用,因為它可能預設在childViewControllerForStatusBarHidden中傳回的是導航棧頂控制器,此時狀态欄由棧頂控制器來決定。如果想讓navigation controller來決定,那麼可以在類中按下面的方式實作:
- (UIViewController *)childViewControllerForStatusBarHidden
{
return nil;
}
此時,狀态欄的管理權在導航控制器。