现在很多 APP 为了保持界面的统一,会让 iOS 状态栏的背景颜色和导航栏的颜色一致,有的时候还会隐藏状态栏,开发中修改状态栏往往一次弄好之后就不会再改变了,下面就记录一下各种调整状态栏颜色以及隐藏状态栏的设置(本文的内容只适用于 iOS7 及以上)
了解一下状态栏(UIStatusBar)
所谓状态栏就是我们的 iPhone 手机屏幕最顶端的20个像素高的那一部分,状态栏左边一般会有手机信号强度、运营商名字、Wi-Fi状态显示,中间会显示时间,状态栏右边会有定位显示、蓝牙显示已经电量显示
状态栏分两个部分:
- 前景部分:就是上面说到的时间、电量等
- 背景部分:就是状态栏背景
如图,上面的状态栏前景黑色,背景白色,下面的状态栏前景白色,背景黑色

设置 UIStatusBar 的前景部分
前景部分也就是时间、电量显示的这部分,有两种设置
- UIStatusBarStyleDefault(默认的黑色)
- UIStatusBarStyleLightContent(白色)
我们可以在 Info.plist 和代码里面设置这两种前景颜色样式
Info.plist 里面设置
在 Info.plist 里增加一个 Status bar style的键,这个键对应的值就是我们需要的 UIStatusBarStyleDefault 或 UIStatusBarStyleLightContent
另外还需要在 Info.plist 增加一个 View controller-based status bar appearance 的键并且值设置为 NO,这样 APP 启动之后前景的颜色样式就是 Info.plist 里面设置的风格了
代码里面设置
用 UIApplication 设置
|
|
这种方法也需要在 Info.plist 增加一个 View controller-based status bar appearance 的键并且值设置为 NO
这里解释一下 View controller-based status bar appearance,这是官方文档的说明:
UIViewControllerBasedStatusBarAppearance (Boolean - iOS) Specifies whether the status bar appearance is based on the style preferred by the view controller that is currently under the status bar. When this key is not present or its value is set to YES, the view controller determines the status bar style. When the key is set to NO, view controllers (or the app) must each set the status bar style explicitly using the UIApplication object.
This key is supported in iOS 7.0 and later.
意思就是: 当该键不存在或其值设置为 YES 时,状态栏的样式由视图控制器决定(下面会讲到),当键设置为 NO 时,视图控制器(或应用程序)必须使用 UIApplication 对象显式地设置状态栏样式,这也解释了为什么上面的 Info.plist 和 UIApplication 设置状态栏样式需要把这个键设置为 NO
UIViewController 里设置
上面使用 UIApplication 设置状态栏的样式的方法在 iOS9 已经被废弃了,苹果推荐使用 UIViewController 的 - preferredStatusBarStyle 方法设置状态栏的样式,我们只需要在 UIViewController 里面重写 - preferredStatusBarStyle 方法,并返回需要的状态栏样式即可
|
|
这个方法需要注意:
- 控制器在显示的时候就会立即调用这个方法,并根据这个方法设置状态栏的样式
- 如果当前控制器已经显示出来了,你还希望可以改变当前的状态栏的样式,就需要用到另一个方法
- setNeedsStatusBarAppearanceUpdate,这个方法会通知系统去调用当前UIViewController的- preferredStatusBarStyle方法,这样就可以重新设置当前控制器页面的状态栏样式了
但是实际使用中我们一般不会单独使用 ViewController 而是把 ViewController 加在 UINavigationController 里面使用,这个时候 ViewController 里面的 - preferredStatusBarStyle 方法并不会被调用,这个时候就需要用到 ViewController 的另一个方法 - childViewControllerForStatusBarStyle
如果是 ViewController 配合 UINavigationController 使用但是又希望状态栏的样式由当前的控制器决定,可以这样做:自定义一个继承自 UINavigationController 的子类,并且重写这个子类的 - childViewControllerForStatusBarStyle 方法:
|
|
重写这个方法的意思就是,不调用当前 UINavigationController 的- preferredStatusBarStyle 方法,而是去调用navigationController.topViewController 的preferredStatusBarStyle 方法,这样就能保证当前显示的UIViewController 的 preferredStatusBarStyle 可以决定状态栏的样式,除了重写子类的方法也可以使用分类的方法可以 参考这里
另外,有时我们当前显示的 UIViewController 可能添加了多个 childViewController,重写当前 UIViewController 的childViewControllerForStatusBarStyle 方法,也可以使 childViewController 的 preferredStatusBarStyle 生效(当前 UIViewController 的 preferredStatusBarStyle 就不会被调用了)
总结起来就是:只要重写 UIViewController 的childViewControllerForStatusBarStyle 方法返回值不是nil,那么这个 UIViewController 的 preferredStatusBarStyle 方法就不会被调用,而是会调用 childViewControllerForStatusBarStyle 这个方法返回的那个UIViewController 的 preferredStatusBarStyle 方法
设置 UIStatusBar 的背景部分
iOS7 以后默认情况下状态栏的背景为透明的,设置它的背景色有两种方法:
第一种是系统方法通过设置 navigationBar 的 barTintColor 颜色来改变状态栏颜色,另一种办法是我们自己写一个 UIView 作为背景添加到状态栏下面,这样就可以随意设置状态栏的颜色了
系统方法
|
|
如果你设置了 navigationBar 的 - setBackgroundImage:(UIImage *)backgroundImage forBarMetrics:(UIBarMetrics)barMetrics ,那么上面的 setBarTintColor 就就失效了
自定义 View
创建一个 UIView,设置该 UIView的 frame 和 statusBar一样({0,-20,self.view.bounds.size.width,20}),然后设置该UIView 的背景色为你希望的状态栏的颜色,然后在 navigationBar 上addSubView 该 UIView 即可,这种方式,可以使状态的背景颜色和导航栏的背景颜色区不一样
状态栏隐藏
状态栏隐藏和设置的状态栏的前景样式方法是类似的,也分为两种情况,一种是在 Info.plist 里面设置,一种是在 `` 里面设置
Info.plist 设置隐藏状态栏
同样的也可以使用 UIApplication 的方法隐藏,但是记住 View controller-based status bar appearance 的要设置为 NO
|
|
有时候我们需要在 APP 启动页面隐藏状态栏,我们需要 Info.plist 里增加一个 Status bar is initially hidden 的键,设置为 YES,这样就 APP 启动页面就会隐藏状态栏
以上的方法也是在 iOS9 之后被废弃了,苹果推荐使用 UIViewController 的 - prefersStatusBarHidden 方法
|
|
这个方法类似 preferredStatusBarStyle,也有一个 childViewControllerForStatusBarHidden 的方法和 - childViewControllerForStatusBarStyle 对应,作用和上面修改状态栏前景样式是一样的,就不再赘述了,但是有点不一样
UIViewController即使和UINavigationController配合使用依然可以在自己的- prefersStatusBarHidden方法里面返回YES隐藏状态栏,只有当UIViewController有多个childViewController并且需要在某个childViewController里面隐藏状态栏,这时候才需要重写UIViewController的childViewControllerForStatusBarHidden返回需要隐藏状态栏的那个childViewController- 另外,调用
- setNeedsStatusBarAppearanceUpdate方法也会刷新- prefersStatusBarHidden方法
以上就是我关于 iOS 状态栏的设置的一些记录
本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!