如何通过代码实现UITableView/UICollectionView滚动到顶部并恢复大导航栏标题?
实现UITableView/UICollectionView滚动至顶部并恢复大标题状态
刚好之前也碰到过类似的问题,来给你梳理下可行的解决方案,既能实现滚动到顶部,又能让导航栏的大标题恢复到初始状态:
一、直接用代码实现滚动+大标题恢复
你之前用scrollToRow能滚动但标题没变大,核心是手动滚动后系统没触发导航栏的大标题状态更新,我们可以在滚动后补一步操作:
1. 针对UITableView
// 先判断是否有数据,避免崩溃 if tableView.numberOfRows(inSection: 0) > 0 { tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top, animated: true) } else { // 空列表时直接设置contentOffset到顶部 tableView.setContentOffset(CGPoint(x: 0, y: -tableView.contentInset.top), animated: true) } // 手动触发导航栏更新,恢复大标题 navigationController?.navigationBar.sizeToFit() // 确保导航项的大标题模式正确 navigationItem.largeTitleDisplayMode = .automatic
2. 针对UICollectionView
逻辑和tableView一致,换对应的滚动方法即可:
if collectionView.numberOfItems(inSection: 0) > 0 { collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .top, animated: true) } else { collectionView.setContentOffset(CGPoint(x: 0, y: -collectionView.contentInset.top), animated: true) } // 同样更新导航栏 navigationController?.navigationBar.sizeToFit()
二、完全模拟点击状态栏的系统行为
其实系统点击状态栏滚动到顶部的行为,是可以通过代码直接触发的,这种方式最省心,因为是原生逻辑,会自动处理大标题的切换:
UIApplication.shared.sendAction(#selector(UIScrollView.scrollToTop), to: nil, from: nil, for: nil)
不过要注意两个前提:
- 你的tableView/collectionView的
scrollsToTop属性是true(默认就是true,除非你手动改成false了) - 当前页面不要有多个开启
scrollsToTop的滚动视图,否则这个方法只会触发第一个符合条件的
三、额外处理:监听滚动状态确保大标题切换
如果上面的方法还是偶尔失效,可以给滚动视图加个滚动监听,当滚动到顶部时强制切换大标题状态:
// 在viewDidLoad里添加监听 tableView.delegate = self // 或者collectionView.delegate = self // 实现UIScrollViewDelegate方法 func scrollViewDidScroll(_ scrollView: UIScrollView) { // 判断是否滚动到了最顶部(考虑contentInset的情况) let isAtTop = scrollView.contentOffset.y <= -scrollView.contentInset.top // 根据状态切换大标题显示模式 navigationItem.largeTitleDisplayMode = isAtTop ? .automatic : .never if isAtTop { navigationController?.navigationBar.sizeToFit() } }
最后补充
别忘了确保你的导航控制器已经开启了大标题功能,也就是在导航控制器初始化或者当前VC的viewDidLoad里设置:
navigationController?.navigationBar.prefersLargeTitles = true
内容的提问来源于stack exchange,提问作者Lifeplus
相关产品推荐
相关产品推荐

