设置UINavigationBar大标题后滚动时仍缩小,如何始终保持大标题?
导航栏大标题滚动时保持大尺寸的问题解决思路
问题复盘
- 已完成配置:导航控制器设置
prefersLargeTitles = true,表视图控制器设置navigationItem.largeTitleDisplayMode = .always - 异常现象:初始显示符合预期,但向上滚动时标题仍会缩小并移至顶部栏项目旁
- 尝试过的无效方案:
- 将UITableViewController嵌入UIViewController的容器视图
- 在UIViewController中直接使用UITableView
- 在UITableView上方添加0高度UIView(此操作会丢失标题的弹跳和缩放效果)
- 特殊表现:静态UITableViewController可正常维持大标题,但子UITableViewController无法实现
临时解决方案(保留标题动画效果)
如果需要保留大标题的弹跳和缩放动画,同时避免滚动时缩小,可尝试以下两种方法:
方法1:拦截滚动事件强制维持大标题
给UITableView添加滚动监听,强制保持导航栏的大标题状态:
override func viewDidLoad() { super.viewDidLoad() tableView.delegate = self navigationController?.navigationBar.prefersLargeTitles = true navigationItem.largeTitleDisplayMode = .always // 监听滚动偏移变化 tableView.addObserver(self, forKeyPath: "contentOffset", options: .new, context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { guard keyPath == "contentOffset" else { return } // 强制刷新导航栏状态,维持大标题 navigationController?.navigationBar.sizeToFit() navigationItem.setLargeTitleDisplayMode(.always) } deinit { tableView.removeObserver(self, forKeyPath: "contentOffset") }
注意:此方法可能存在轻微视觉抖动,需根据实际场景调整。
方法2:自定义导航栏标题视图
完全脱离系统大标题逻辑,用自定义UILabel模拟大标题效果:
override func viewDidLoad() { super.viewDidLoad() // 隐藏系统默认标题 navigationItem.title = "" // 创建自定义大标题标签 let largeTitleLabel = UILabel() largeTitleLabel.text = "你的标题文本" largeTitleLabel.font = UIFont.preferredFont(forTextStyle: .largeTitle).withTraits(traits: .traitBold) largeTitleLabel.textColor = .label // 将标签作为左侧BarButtonItem添加到导航栏 navigationItem.leftBarButtonItem = UIBarButtonItem(customView: largeTitleLabel) // 配置约束,确保标签位置符合大标题布局 largeTitleLabel.translatesAutoresizingMaskIntoConstraints = false guard let navBar = navigationController?.navigationBar else { return } NSLayoutConstraint.activate([ largeTitleLabel.centerYAnchor.constraint(equalTo: navBar.centerYAnchor), largeTitleLabel.leadingAnchor.constraint(equalTo: navBar.leadingAnchor, constant: 16) ]) } // 扩展UIFont,添加便捷的加粗方法 extension UIFont { func withTraits(traits: UIFontDescriptor.SymbolicTraits) -> UIFont { guard let descriptor = fontDescriptor.withSymbolicTraits(traits) else { return self } return UIFont(descriptor: descriptor, size: 0) } }
此方法可完全控制标题样式与行为,不受滚动影响,但如需弹跳/缩放动画,需自行实现。
关于UIKit Bug的说明
根据测试结果,静态UITableViewController正常但子UITableViewController异常,这大概率是UIKit内部逻辑问题。在已向Apple提交反馈的前提下,建议:
- 关注后续iOS版本更新,确认问题是否修复
- 反馈时附上测试项目,帮助Apple更快定位问题
内容的提问来源于stack exchange,提问作者Mof
相关产品推荐
相关产品推荐

