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

iOS 16.4带返回按钮的导航栏多行标题实现方案咨询

iOS 16.4 带返回按钮的导航栏添加多行标题解决方案

问题说明

在iOS 16.4环境下,需要为带有返回按钮的导航栏实现多行标题显示。此前尝试Stack Overflow上@krunal、@Kaiv Mata等人的方案,但在存在返回按钮时均无法生效;@Ankur Lahiry提出的私有API方案item.setValue(true, forKey: "__largeTitleTwoLineMode")虽能实现效果,但会导致App审核被拒,还会破坏下拉刷新功能,无法采用。

当前使用的代码如下:

guard let navigationBar = self.navigationController?.navigationBar else { return }
navigationController?.navigationBar.subviews.forEach({ subview in
    subview.subviews.forEach { subsubview in
        guard let label: UILabel = subsubview as? UILabel else { return }
        label.text = "Multiline title with back button that not fit in one line"
        label.backgroundColor = .yellow
        label.font = UIFont.systemFont(ofSize: 16)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        label.sizeToFit()
        navigationBar.frame.size.height = 50 + label.frame.height
        navigationItem.title = label.text
    }
})

已尝试的操作均未解决问题:

  • 在ViewDidAppear()和ViewWillAppear()中执行上述代码
  • 设置extendedLayoutIncludesOpaqueBars = false
  • 设置tableView.contentInset = UIEdgeInsets(top: 100, left: 0, bottom: 0, right: 0)

当前问题:第二行标题被遮挡;预期效果:标题完整多行显示且不影响返回按钮布局。


有效解决方案(非私有API)

方法1:自定义导航栏标题视图

直接为navigationItem.titleView设置自定义多行UILabel,同时调整导航栏高度约束,确保标题完整显示且不与返回按钮冲突。

代码示例:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // 创建自定义多行标题Label
    let titleLabel = UILabel()
    titleLabel.text = "Multiline title with back button that not fit in one line"
    titleLabel.font = UIFont.systemFont(ofSize: 16)
    titleLabel.numberOfLines = 0
    titleLabel.lineBreakMode = .byWordWrapping
    titleLabel.textAlignment = .center
    titleLabel.backgroundColor = .yellow
    
    // 计算Label适配尺寸,预留返回按钮及边距空间
    let maxWidth = UIScreen.main.bounds.width - 80
    let labelSize = titleLabel.sizeThatFits(CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude))
    titleLabel.frame = CGRect(x: 0, y: 0, width: maxWidth, height: labelSize.height)
    
    // 设置为导航栏标题视图
    navigationItem.titleView = titleLabel
    
    // 调整导航栏高度约束
    guard let navigationBar = navigationController?.navigationBar else { return }
    // 移除原有高度约束
    navigationBar.constraints.forEach { constraint in
        if constraint.firstAttribute == .height {
            constraint.isActive = false
        }
    }
    // 设置新高度(基础高度44 + 上下边距)
    let newBarHeight = max(44, labelSize.height + 16)
    navigationBar.heightAnchor.constraint(equalToConstant: newBarHeight).isActive = true
    
    // 适配TableView内容偏移,避免被导航栏遮挡
    if let tableView = view as? UITableView {
        let extraInset = newBarHeight - 44
        tableView.contentInset = UIEdgeInsets(top: extraInset, left: 0, bottom: 0, right: 0)
        tableView.scrollIndicatorInsets = tableView.contentInset
    }
}

方法2:使用UINavigationBarAppearance(iOS 13+)

通过UINavigationBarAppearance统一配置导航栏样式,实现多行标题自适应:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    let appearance = UINavigationBarAppearance()
    appearance.configureWithDefaultBackground()
    
    // 创建多行标题Label
    let titleLabel = UILabel()
    titleLabel.text = "Multiline title with back button that not fit in one line"
    titleLabel.font = UIFont.systemFont(ofSize: 16)
    titleLabel.numberOfLines = 0
    titleLabel.lineBreakMode = .byWordWrapping
    titleLabel.textAlignment = .center
    
    let maxWidth = UIScreen.main.bounds.width - 80
    let labelSize = titleLabel.sizeThatFits(CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude))
    titleLabel.frame = CGRect(x: 0, y: 0, width: maxWidth, height: labelSize.height)
    
    // 将自定义Label设置到Appearance中
    appearance.titleView = titleLabel
    
    // 应用样式到导航栏
    navigationController?.navigationBar.standardAppearance = appearance
    navigationController?.navigationBar.scrollEdgeAppearance = appearance
    
    // 调整导航栏高度
    let newBarHeight = max(44, labelSize.height + 16)
    navigationController?.navigationBar.frame.size.height = newBarHeight
    
    // 适配TableView内容偏移
    if let tableView = view as? UITableView {
        let extraInset = newBarHeight - 44
        tableView.contentInset = UIEdgeInsets(top: extraInset, left: 0, bottom: 0, right: 0)
    }
}

注意事项

  1. 避免直接遍历导航栏子视图修改内部控件,iOS不同版本导航栏结构可能变化,导致代码失效
  2. 调整导航栏高度后,必须同步修改scrollView(如UITableView)的contentInset和scrollIndicatorInsets,防止内容被遮挡
  3. 自定义标题视图时需预留返回按钮的宽度空间,避免标题与返回按钮重叠

内容的提问来源于stack exchange,提问作者Aysen Eremeev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 10:54:53