ios 11 custom navbar goes under status bar

24,158

Solution 1

Your code was always wrong. You should not be setting the height of a manually added navigation bar yourself or placing it at the top of the view. You should pin the top of the navigation bar to the bottom of the status bar (e.g. the top of the Safe Area) and give it a delegate so that you can use the UIBarPositioningDelegate mechanism to set its position to .topAttached, which will cause it to stretch up to the top of the screen correctly.

(But you should also be asking yourself why you are adding a navigation bar manually. There is usually no reason not to wrap your view controller in a UINavigationController — even if you don't intend to do any actual navigation — just to get the navigation bar, with all its automatic management.)

Solution 2

See ios 11 custom navbar goes under status bar / ios 11 navigation bar overlap status bar for an answer

Not sure if this is the same issue, but we ran into this as well when upgrading to iOS 11.

See ios 11 custom navbar goes under status bar

We were manually setting nav bar height to 64 and pinning to the superview edges. Conforming to the UINavigationBarDelegate protocol and implementing the UIBarPositioningDelegate delegate method solved it for us.

We replaced

navigationBar.autoPinEdgesToSuperviewEdgesExcludingEdge(.bottom)
navigationBar.autoSetDimension(.height, toSize: 64)

with

...
  if #available(iOS 11.0, *) {
    navigationBar.topAnchor.constraint(
      equalTo: self.view.safeAreaLayoutGuide.topAnchor
    ).isActive = true
  } else {
    navigationBar.topAnchor.constraint(
      equalTo: topLayoutGuide.bottomAnchor
    ).isActive = true
  }
  navigationBar.autoPinEdge(toSuperviewEdge: .left)
  navigationBar.autoPinEdge(toSuperviewEdge: .right)
  navigationBar.delegate = self
...

public func position(for bar: UIBarPositioning) -> UIBarPosition
  return .topAttached
}

This is using the purelayout DSL for some of the autolayout calls (https://github.com/PureLayout/PureLayout)

Credit goes to https://stackoverflow.com/users/341994/matt for an answer

Solution 3

Try adding some Auto Layout constraints after you add the nav bar to the view

if #available(iOS 11.0, *) {
    newNavbar.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    newNavbar.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    newNavbar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    newNavbar.heightAnchor.constraint(equalToConstant: 64).isActive = true
}

You can actually use all but the third constraint in earlier versions of iOS but if it all works in earlier versions you may not want to mess with it.

Using the safe layout area should keep your nav bar under the status bar.

Solution 4

First of all, make sure that your navigation controller's "shows navigation bar" is unchecked in storyboard.

Then, drag and drop navigation bar from the "object library". Give Top constraint equal to 20.

It'll also work perfect in "iPhone X simulator".

Happy Coding!

Solution 5

Tried this solution in Swift 4.1

let menuBar: UIView = {
let mb = UIView()
mb.backgroundColor = .red
mb.translatesAutoresizingMaskIntoConstraints = false
return mb
}()



private func setupMenuBar(){

view.addSubview(menuBar)

let constraints = [ menuBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                    menuBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                    menuBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                    menuBar.heightAnchor.constraint(equalToConstant: 50)]
NSLayoutConstraint.activate(constraints)
}
Share:
24,158
iknowNothing
Author by

iknowNothing

Updated on September 29, 2020

Comments

  • iknowNothing
    iknowNothing almost 4 years

    just downloaded xcode 9 and i'm having this weird issue, on ios 11 my custom navbar appears to be half in size and is under the status bar, on ios 10 works fine.

    so here is my code

    let newNavbar: UINavigationBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 64))
    let navItem = UINavigationItem()
    
    //create and assign the items
    
    newNavbar.setItems([navItem], animated: false)
    view.addSubview(newNavbar)
    

    here is a screenshot, ios11 on the left and ios10 on the right,

    enter image description here

  • iknowNothing
    iknowNothing almost 7 years
    i have to create a custom navbar though, can i create a new one without providing height and adding it to the view? the reason is in my nested Detail View i'm using a UIimage as a navbar with a blur, using the default one ruins that.
  • matt
    matt almost 7 years
    Try doing what I suggested, then.
  • iknowNothing
    iknowNothing almost 7 years
    about the first suggestion it doesn't seem i can use it with a custom navbar. about the second i tried the system navbar but it causes another issues with the nested Detail view, see here i.imgur.com/PAb5Thy.png left with custom navbar and right with the default. creating my sutom navbars worked well until ios11
  • matt
    matt almost 7 years
    "about the first suggestion it doesn't seem i can use it with a custom navbar" Then you're not doing what I said, because I do this with success.
  • iknowNothing
    iknowNothing almost 7 years
    after messing with it for some time i ran into the same issue see here i.imgur.com/NUYcdp4.png i've added a delegate and confirmed .topAttached function is executing. what am i doing wrong?
  • matt
    matt almost 7 years
    You have a top space constraint of zero to the superview. That is not what I said to do. In fact, it is exactly what I said not to do.
  • iknowNothing
    iknowNothing almost 7 years
    dammit, you're right its working now, thanks i really appreciate it.
  • Nevin Jethmalani
    Nevin Jethmalani almost 7 years
    You are saying here that there is no reason to add a navigation bar manually. What about when you are using a modal segue? Even if your VC is embedded into a navigation controller, the nav bar does not show up when using a modal segue. Am I doing something wrong here?
  • matt
    matt almost 7 years
    @NevinJethmalani Yes, you must be. Nothing prevents modal segue to navigation controller. If you want help, ask this as a real question so I can see the actual problem. Thanks!
  • Nevin Jethmalani
    Nevin Jethmalani almost 7 years
    @matt This is saying that the nav bar disappears. If this is wrong as well, I will go ahead and open up a new question. stackoverflow.com/questions/15689261/…
  • matt
    matt almost 7 years
    @NevinJethmalani The nav bar doesn't "disappear". If you do a modal segue, you are covering the whole screen, including the nav bar. No surprise there.
  • Nevin Jethmalani
    Nevin Jethmalani almost 7 years
    @matt Perfect. Sorry for the confusion. That is what I thought as well. Is it better practice to embed the view in a new navigation controller or just put a nav bar in place when we segue modally? This is to display a shopping cart from the main view for example.
  • matt
    matt almost 7 years
    As I said in my answer, if you need a nav bar in the presented view controller, then segue to a navigation controller. But remember, you'll still need a way to dismiss; you can't go "Back" to dismiss.
  • Apoorv Khatreja
    Apoorv Khatreja over 6 years
    @matt Can you comment on how to actually "pin the top of the navigation bar to the bottom of the status bar"? As far as I'm aware, there is no reference available to the status bar view (just the frame). I'm assuming you meant setting an autolayout constraint that does this.
  • matt
    matt over 6 years
    @ApoorvKhatreja In iOS 11 / Xcode 9 it would be the safe area layout guide top anchor. Before that it would be the bottom of the top layout guide.
  • nefarianblack
    nefarianblack about 6 years
    @matt you are the saviour. I have been pulling my hair out for past 4 hours as to why my setBackgroundImage(_, for:, barMetrics:) was not working even when I set UIBarPosition to topAttached.
  • dineshprasanna
    dineshprasanna about 6 years
    we are getting crash when try to set a new constraints which you have mentioned
  • Lohith Korupolu
    Lohith Korupolu over 4 years
    @dineshprasanna - have you solved this crash issue? what is the problem? I too get a crash saying "they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal."