You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何增高自定义UINavigationBar并添加UIView?适配iOS 11+

解决自定义UINavigationBar增高并添加额外视图的问题(iOS11+)

嘿,我之前也踩过这个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:32:26