轉載http://jumpingfrog0.github.io/2016/2016-03-26-status-bar-hidden/
Status Bar 的正常隱藏
view-controllers 控制 status bar 的隱藏
在iOS 9中,status bar 的隱藏默認是通過 view-controlls 控制的,即每個控制器決定是否隱藏 status bar 。
只需在 controller 中重載 prefersStatusBarHidden 函數
override func prefersStatusBarHidden() -> Bool {
return true
}
全局控制 status bar 的隱藏
如果想要全局控制,只需兩步:
- 在Info.plist中,添加屬性
View controller-based status bar appearance為NO -
添加如下代碼
UIApplication.sharedApplication().statusBarHidden = true
- 如果想改成每個控制器自行控制,將
View controller-based status bar appearance為YES即可
Status Bar 隱藏不了的情況
但是,有時候也會有意外發生,上述方法並不能如願隱藏 status bar ,那就是 在ParentViewController 中添加一個全屏的 ChildViewController ,此時想用ChildViewController 來控制狀態欄時 ,就會失效,即使 ChildViewController 中的prefersStatusBarHidden方法返回的是YES,也無法隱藏 status bar 。
解決辦法是:重載 childViewControllerForStatusBarHidden方法
如果你想要讓你的 container view controller 的 child view controller 控制 status bar 的隱藏狀態的話,就重載該方法,決定使用哪個 child view controller 來控制 隱藏/非隱藏 的狀態。如果返回 nil 或不重載該方法,就用它自己來控制 status bar 的狀態。可以通過調用 setNeedsStatusBarAppearanceUpdate 方法來改變該方法返回的值,即再調用該方法一次。
class StatusBarHiddenParentController: UIViewController {
var childController: StatusBarHiddenChildController?
override func viewDidLoad() {
super.viewDidLoad()
childController = StatusBarHiddenChildController.fromStoryboard("Main")
addChildViewController(childController!)
view.addSubview(childController!.view)
setNeedsStatusBarAppearanceUpdate()
}
override func childViewControllerForStatusBarHidden() -> UIViewController? {
return childController
}
override func prefersStatusBarHidden() -> Bool {
return false
}
}
class StatusBarHiddenChildController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
上述代碼最終能將狀態欄隱藏,即使在 StatusBarHiddenParentController 中的prefersStatusBarHidden返回的是NO
注意:因為childViewControllerForStatusBarHidden會比viewDidLoad 先調用,所以在viewDidLoad中要調用setNeedsStatusBarAppearanceUpdate
有時候我們需要關閉控制器視圖,如下列三種情況:
- 將控制器從navigationController的堆棧中pop出去
- 將present出來的控制器dismiss掉
- 將子控制器從父控制器中移除
push 和 present 兩種方式展示的 view controller 在 pop 和 dismiss 時都能夠自動還原 status bar 的狀態。但是,把子控制器從父控制器中移除時,就會出現奇怪的問題, status bar並不能自動還原,因此還需要特別處理。
我們可以設置一個Bool變量 statusBarHidden 用來記錄目前 statusBar 是否隱藏,在 prefersStatusBarHidden 函數中返回 statusBarHidden值。在要移除子控制器的函數中做兩步操作:
- 先將
statusBarHidden設置為False, 並調用setNeedsStatusBarAppearanceUpdate刷新狀態欄 - 再將子控制器移除。
class StatusBarHiddenRemoveWayChildController: UIViewController {
var statusBarHidden: Bool = true
override func viewDidLoad() {
super.viewDidLoad()
let removeButton = UIButton(frame: CGRectMake(30, 80, 100, 30))
removeButton.setTitle("remove", forState: .Normal)
removeButton.addTarget(self, action: "remove", forControlEvents: .TouchUpInside)
view.addSubview(removeButton)
}
// 1. set `statusBarHidden` into `false`, and then refresh status bar
// 2. remove from parent controller
func remove() {
statusBarHidden = false
setNeedsStatusBarAppearanceUpdate()
view.removeFromSuperview()
removeFromParentViewController()
}
override func prefersStatusBarHidden() -> Bool {
return statusBarHidden
}
}
滾動ScrollView或TableView時隱藏Status Bar和Navigation Bar
京東和淘寶客戶端的商品搜索結果頁面,在滾動時可以隱藏 status bar 和 navigation bar ,我自認為這是一個很好的設計,身為一個有追求的程序員,這個功能的實現那當然也不能放過啦~~
NavigationController 有一個屬性 hidesBarsOnSwipe,可以實現輕掃時隱藏 navigation bar ,與之對應的手勢是它的另一個屬性barHideOnSwipeGestureRecognizer,只要給這個手勢添加一個方法來控制 status bar ,就可以實現同時隱藏 status bar 和 navigation bar 了。
class StatusBarAndNavigationBarHiddenOnSwipeController: UITableViewController {
var hideStatusBar = false
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.grayColor()
navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "swipe:")
navigationController?.hidesBarsOnSwipe = true
}
override func prefersStatusBarHidden() -> Bool {
return hideStatusBar
}
func swipe(recognizer: UISwipeGestureRecognizer) {
hideStatusBar = navigationController?.navigationBar.frame.origin.y < 0
UIView.animateWithDuration(0.2) { () -> Void in
self.setNeedsStatusBarAppearanceUpdate()
}
}
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return .Slide
}
}
