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

iOS11中如何固定开启prefersLargeTitle的UINavigationBar高度?

解决大标题模式下固定UINavigationBar高度的问题

我完全懂你的困扰——开启prefersLargeTitle后,哪怕你给导航栏标题用了自定义固定字体,系统还是会跟着用户设置的文本大小自动调整导航栏高度,之前设置的高度锚点没效果,是因为系统导航栏的内置布局逻辑会直接覆盖你的约束。下面给你两个实用的解决方案:

方案一:自定义UINavigationBar重写尺寸计算

这是最直接的思路,通过自定义导航栏类,强制返回你想要的固定高度:

class FixedLargeTitleNavBar: UINavigationBar {
    // 这里设置你需要的固定高度,大标题模式默认高度是96,可根据需求调整
    private let fixedHeight: CGFloat = 96
    
    override func sizeThatFits(_ size: CGSize) -> CGSize {
        var fittingSize = super.sizeThatFits(size)
        fittingSize.height = fixedHeight
        return fittingSize
    }
    
    // 额外保险:确保布局过程中也维持固定高度
    override func layoutSubviews() {
        super.layoutSubviews()
        bounds.size.height = fixedHeight
    }
}

使用方式

  • 代码创建导航控制器时:
    let navController = UINavigationController(navigationBarClass: FixedLargeTitleNavBar.self, toolbarClass: nil)
    navController.viewControllers = [YourTargetViewController()]
    
  • Storyboard中使用:选中导航栏,在Identity Inspector里把Class改成FixedLargeTitleNavBar即可。

方案二:用KVO监听并强制修正高度

如果不想自定义导航栏类,可以在目标ViewController里通过KVO监听导航栏的bounds变化,一旦高度偏离预期就强制修正:

class YourTargetViewController: UIViewController {
    private let fixedNavBarHeight: CGFloat = 96
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 开启大标题并设置自定义字体
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationController?.navigationBar.largeTitleTextAttributes = [
            .font: UIFont(name: "YourCustomFontName", size: 34)!
        ]
        
        // 添加KVO监听导航栏bounds变化
        navigationController?.navigationBar.addObserver(self, forKeyPath: "bounds", options: .new, context: nil)
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard keyPath == "bounds", let navBar = object as? UINavigationBar else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }
        
        // 检查高度是否符合预期,不符合则强制调整
        if navBar.bounds.height != fixedNavBarHeight {
            navBar.bounds.size.height = fixedNavBarHeight
            navBar.setNeedsLayout()
            navBar.layoutIfNeeded()
        }
    }
    
    // 记得在控制器销毁时移除观察者,避免内存泄漏
    deinit {
        navigationController?.navigationBar.removeObserver(self, forKeyPath: "bounds")
    }
}

小提醒

固定导航栏高度可能会影响App的无障碍体验,如果你的App需要支持动态文本大小,建议先权衡是否真的要固定高度;另外,使用自定义字体时,要确保字体文件已正确导入项目,且在Info.plist中声明了字体名称。

内容的提问来源于stack exchange,提问作者Ahmed Khedr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:20:21