iOS开发:两个CollectionView滚动均触发导航栏缩小的实现问题
双CollectionView切换时导航栏大标题收缩问题解决方案
核心原因
iOS导航控制器默认只会监听视图层级中最上层(或第一个添加)的UIScrollView(包含UICollectionView)的滚动事件,以此调整大标题的收缩状态。切换CollectionView时,若未手动更新监听目标,导航控制器仍会绑定最初的滚动视图,导致新显示的CollectionView无法触发导航栏收缩。
解决方法
方法1:切换时手动绑定当前滚动视图
修改handleFeedsTransitionAnimation方法,在动画完成后指定当前显示的CollectionView为导航栏监听目标,并触发一次滚动事件更新状态:
private func handleFeedsTransitionAnimation() { switch feedsType { case .discovery: UIView.animate(withDuration: 0.4, animations: { [weak self] in guard let this = self else { return } this.discoveryCollectionView.isHidden = false this.discoveryViewLeadingAnchor.constant = 0 this.friendsViewTrillingAnchor.constant = this.screenSize this.view.layoutIfNeeded() }, completion: { [weak self] _ in guard let this = self else { return } this.friendsCollectionView.isHidden = true // 绑定当前显示的CollectionView到导航栏 this.discoveryCollectionView.delegate = self this.navigationController?.navigationItem.scrollEdgeAppearance = this.navigationController?.navigationItem.standardAppearance // 手动触发滚动事件,强制导航栏更新状态 this.discoveryCollectionView.setContentOffset(this.discoveryCollectionView.contentOffset, animated: false) }) case .friends: UIView.animate(withDuration: 0.4, animations: { [weak self] in guard let this = self else { return } this.friendsCollectionView.isHidden = false this.discoveryViewLeadingAnchor.constant = -this.screenSize this.friendsViewTrillingAnchor.constant = 0 this.view.layoutIfNeeded() }, completion: { [weak self] _ in guard let this = self else { return } this.discoveryCollectionView.isHidden = true // 绑定当前显示的CollectionView到导航栏 this.friendsCollectionView.delegate = self this.navigationController?.navigationItem.scrollEdgeAppearance = this.navigationController?.navigationItem.standardAppearance // 手动触发滚动事件,强制导航栏更新状态 this.friendsCollectionView.setContentOffset(this.friendsCollectionView.contentOffset, animated: false) }) } }
同时确保视图控制器遵守UICollectionViewDelegate协议:
class YourViewController: UIViewController, UICollectionViewDelegate { // ... 现有代码 }
方法2:通过代理强制更新导航栏
让视图控制器作为两个CollectionView的共同代理,在滚动时手动触发导航栏布局更新:
extension YourViewController: UICollectionViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { // 强制导航栏更新布局,响应滚动事件 navigationController?.navigationBar.sizeToFit() navigationController?.view.layoutIfNeeded() } }
注意在切换CollectionView时,要确保当前显示的CollectionView的delegate被设置为视图控制器(参考方法1中的绑定逻辑)。
方法3:调整视图层级(不推荐)
每次切换完成后,将当前显示的CollectionView移到视图层级最前面:
// 在动画完成的completion闭包中添加 view.bringSubviewToFront(this.discoveryCollectionView) // 切换到friends时替换为friendsCollectionView
此方法虽能解决问题,但会增加视图层级操作的复杂度,优先推荐前两种方法。
内容的提问来源于stack exchange,提问作者martin wotterman
相关产品推荐
相关产品推荐

