ios 11 custom navbar goes under status bar

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!


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.


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.)


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

Tags:

Swift

Ios11