轉載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 } }