ios 11 个自定义导航栏位于状态栏下方

ios 11 custom navbar goes under status bar

刚刚下载 xcode 9 我遇到了这个奇怪的问题,在 ios 11 我的自定义导航栏看起来只有一半大小并且在状态栏下面,在 ios 10 工作正常。

所以这是我的代码

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)

这里是截图,左边ios11,右边ios10,

将导航栏添加到视图后,尝试添加一些自动布局约束

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
}

您实际上可以在 iOS 的早期版本中使用除第三个约束之外的所有约束,但如果它在早期版本中都有效,您可能不想弄乱它。

使用安全布局区域应将导航栏保持在状态栏下方。

您的代码总是错误的。您不应该自己设置手动添加的导航栏的高度或将其放置在视图的顶部。您应该将导航栏的顶部固定到状态栏的底部(例如安全区域的顶部)并给它一个委托,以便您可以使用 UIBarPositioningDelegate 机制将其位置设置为 .topAttached,这将使它正确地伸展到屏幕的顶部。

(但你也应该问问自己 为什么 你要手动添加导航栏。通常没有理由不将你的视图控制器包装在 UINavigationController 中——即使你不打算做任何实际的导航 — 只是为了获得导航栏及其所有自动管理。)

请参阅 / ios 11 navigation bar overlap status bar 以获得答案

不确定这是否是同一个问题,但我们 运行 在升级到 iOS 11 时也遇到了这个问题。

我们手动将导航栏高度设置为 64 并固定到超级视图边缘。符合 UINavigationBarDelegate 协议并实现 UIBarPositioningDelegate 委托方法为我们解决了它。

我们更换了

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

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

这是为某些自动布局调用使用 purelayout DSL (https://github.com/PureLayout/PureLayout)

感谢 https://whosebug.com/users/341994/matt 的回答

首先,确保您的导航控制器的 "shows navigation bar" 在故事板中未选中。

然后,从 "object library" 拖放导航栏。将 Top 约束设为 20。

它在 "iPhone X simulator" 中也能完美运行。

编码愉快!

在 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)
}