如何增高自定义UINavigationBar并添加UIView?适配iOS 11+
嘿,我之前也踩过这个iOS11+自定义导航栏增高的坑!其实核心是要适配iOS11之后导航栏的Auto Layout布局逻辑,直接改frame肯定会被系统覆盖,给你一套亲测有效的方案:
1. 自定义UINavigationBar子类,搞定增高和额外视图
我们需要重写导航栏的intrinsicContentSize来让系统识别到导航栏的新高度,同时把额外的黄色视图添加到导航栏上,还要调整原有导航元素的位置避免被遮挡:
class CustomNavigationBar: UINavigationBar { // 你要添加的额外视图(黄色区域) let extraBottomView = UIView() override init(frame: CGRect) { super.init(frame: frame) setupExtraView() } required init?(coder: NSCoder) { super.init(coder: coder) setupExtraView() } private func setupExtraView() { extraBottomView.backgroundColor = .yellow addSubview(extraBottomView) // 开启自动布局,关闭自动掩码 extraBottomView.translatesAutoresizingMaskIntoConstraints = false // 约束:左右贴导航栏,底部对齐,高度设为你需要的数值(比如44) NSLayoutConstraint.activate([ extraBottomView.leadingAnchor.constraint(equalTo: leadingAnchor), extraBottomView.trailingAnchor.constraint(equalTo: trailingAnchor), extraBottomView.bottomAnchor.constraint(equalTo: bottomAnchor), extraBottomView.heightAnchor.constraint(equalToConstant: 44) ]) } // 重写这个属性告诉系统导航栏的新高度 override var intrinsicContentSize: CGSize { let originalSize = super.intrinsicContentSize // 原有高度(已经包含刘海屏的status bar高度)加上额外视图的高度 return CGSize(width: originalSize.width, height: originalSize.height + 44) } override func layoutSubviews() { super.layoutSubviews() // 调整导航栏内部的内容容器位置,避免被额外视图挡住 for subview in subviews { let subviewClassName = String(describing: type(of: subview)) // iOS11+导航栏的内容容器类名包含"ContentView" if subviewClassName.contains("ContentView") { // 把内容容器的高度设为导航栏总高度减去额外视图的高度 subview.frame = CGRect( x: subview.frame.origin.x, y: subview.frame.origin.y, width: subview.frame.width, height: bounds.height - 44 ) } } } }
2. 在导航控制器中使用自定义导航栏
不管是代码创建还是Storyboard,都要把导航控制器的导航栏替换成我们自定义的:
代码创建导航控制器的情况:
class CustomNavController: UINavigationController { override func viewDidLoad() { super.viewDidLoad() // 替换成自定义导航栏 navigationBar = CustomNavigationBar() navigationBar.isHidden = false } }
Storyboard的情况:
选中导航控制器的Navigation Bar,在Identity Inspector里把Class改成CustomNavigationBar即可。
3. 避坑提示
- 绝对不要直接修改
navigationBar.frame:iOS11之后导航栏由Auto Layout管理,手动改frame会被系统的布局逻辑覆盖。 - 不要用
setTitleVerticalPositionAdjustment:这个方法只能调整标题的垂直位置,无法改变整个导航栏的高度。 - 额外视图的交互:如果要在黄色区域加按钮、标签,直接往
extraBottomView上添加子视图就行,和普通视图的交互处理完全一致。
内容的提问来源于stack exchange,提问作者Evgeny
相关产品推荐
相关产品推荐

