19

iOS 8 adds a super new cool feature: hiding the navigation bar when user is scrolling.

This with a single line in viewDidload :

navigationController?.hidesBarsOnSwipe = true

Cool, isn't it?

But now I have a little problem: when the navigation bar is hidden, the status bar is still here and overlaps content, which is ugly.

What should I do to make it hidden when the navigation bar is hidden?

Tim
  • 8,932
  • 4
  • 43
  • 64
jmcastel
  • 1,365
  • 7
  • 17
  • 34
  • hey, did you ever find out how to do this? thanks! – dot Nov 19 '14 at 00:58
  • No unfortunately...could you add +1 ? – jmcastel Nov 19 '14 at 09:02
  • Take a look at my question: http://stackoverflow.com/questions/25870382/how-to-prevent-status-bar-from-overlapping-content-with-hidesbarsonswipe-set-on – Michał Ciuba Nov 24 '14 at 20:52
  • Thanks but it s obj c solution and I am really new to dev also only understand swift language . It s hard to translate it to swift version. Could you help me doing this ? – jmcastel Nov 24 '14 at 21:21

5 Answers5

14

Override the following methods on UIViewController:

extension MyViewController {
  override func prefersStatusBarHidden() -> Bool {
    return barsHidden // this is a custom property
  }

  // Override only if you want a different animation than the default
  override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
    return .slide
  }
}

Update barsHidden somewhere in the code and call setNeedsStatusBarAppearanceUpdate()

Xanndarr
  • 3
  • 2
Yariv Nissim
  • 13,273
  • 1
  • 38
  • 44
1

This is fixed problem for in Xcode 6.1

navigationController?.navigationBar.hidden = true

Ali Raza
  • 2,796
  • 1
  • 20
  • 24
0

I am basing this answer on some comments on this post, which are speculation. I am not sure if this will work, because Apple does not give us any direct way or delegate method for when the navigation bar hides.

Subclass UINavigationBar as NavigationBar. Add a property observer to its hidden property like so:

var hidden: Bool{
didSet{
    UIApplication.sharedApplication().setStatusBarHidden(self.hidden, animation: .Slide)
}
}

You want to then go to your viewDidLoad method in your main view controller, and set your self.navigationBar property (or self.navigationController.navigationBar, not sure which one) to an instance of your new NavigationBar class.

Note that I cannot test this right now, let me know how/if this works.

erdekhayser
  • 6,537
  • 2
  • 37
  • 69
  • It doesn't. Where do i have to put the var hidden declaration ? self.navigationController.navigationBar give me "UINavigationController does not have a member called navigationBar". self.navigationBar give me "myTableViewController does not have a member called navigationBar" – jmcastel Oct 07 '14 at 10:12
  • @jmcastel Doesn't UINavigationController have a navigation bar? https://developer.apple.com/library/ios/documentation/Uikit/reference/UINavigationController_Class/index.html#//apple_ref/occ/instp/UINavigationController/navigationBar – erdekhayser Oct 07 '14 at 12:22
0

You could detect swipes by using UISwipeGestureRecognizer. I'm using it on UIWebView:

In viewDidLoad I have:

let swipeUp = UISwipeGestureRecognizer(target: self, action: "didSwipe")
let swipeDown = UISwipeGestureRecognizer(target: self, action: "didSwipe")
swipeUp.direction = UISwipeGestureRecognizerDirection.Up
swipeDown.direction = UISwipeGestureRecognizerDirection.Down
webView.addGestureRecognizer(swipeUp)
webView.addGestureRecognizer(swipeDown)
navigationController?.hidesBarsOnSwipe = true

I also have an extension to my viewcontroller, called WebViewViewController:

extension WebViewViewController {
    override func prefersStatusBarHidden() -> Bool {
        return hideStatusBar
    }

    override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
        return UIStatusBarAnimation.Slide
    }
}

On a class level in my WebViewViewController I also have:

var hideStatusBar = false

func didSwipe() {
    hideStatusBar = true   
}
Andrej
  • 7,266
  • 4
  • 38
  • 57
0

Okay I spent all day doing this, hopefully this helps some people out. There's a barHideOnSwipeGestureRecognizer. So you could make a listener for the corresponding UIPanGesture, noting that if the navigation bar is hidden then its y origin is -44.0; otherwise, it's 0 (not 20 because we hid the status bar!).

In your view controller:

 // Declare at beginning
var curFramePosition: Double!
var showStatusBar: Bool = true
self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")

...

override func viewDidLoad(){
    self.navigationController?.hidesBarsOnSwipe = true
  curFramePosition = 0.0 // Not hidden
  self.navigationController?.barHideOnSwipeGestureRecognizer.addTarget(self, action: "didSwipe:")
  ...
}

func didSwipe(swipe: UIPanGestureRecognizer){
    // Visible to hidden
    if curFramePosition == 0 && self.navigationController?.navigationBar.frame.origin.y == -44 {
        curFramePosition = -44
        showStatusBar = false
        prefersStatusBarHidden()
        setNeedsStatusBarAppearanceUpdate()
    }
    // Hidden to visible
    else if curFramePosition == -44 && self.navigationController?.navigationBar.frame.origin.y == 0 {
        curFramePosition = 0
        showStatusBar = true
        prefersStatusBarHidden()
        setNeedsStatusBarAppearanceUpdate()
    }
}

override func prefersStatusBarHidden() -> Bool {
    if showStatusBar{
        return false
    }
    return true
}
goodcow
  • 4,495
  • 6
  • 33
  • 52