使用paging正交滚动时scrollToItem()导致UICollectionView组合布局显示异常
问题产生原因
- 该问题属于iOS 15系统中
UICollectionViewCompositionalLayout搭配正交滚动分页类行为的原生Bug。当调用scrollToItem()方法时,系统内部计算正交滚动区域的布局偏移时,错误将当前section的header高度、section的contentInset.top值叠加到了正交滚动容器的contentOffset.y上,但是该偏移值没有同步给同section的footer以及后续内容的布局计算,最终导致cell整体向下偏移覆盖后续内容。 - 手动触发滚动时,系统会重新校验正交滚动区的布局参数,错误的y偏移会被重置,因此cell会回到正确位置,只有代码触发滚动且使用系统分页行为时才会触发该问题。
可行解决方案
方案1:替换滚动实现逻辑
- 禁用
scrollToItem()的动画参数,实测非动画调用时不会触发该布局bug:
collectionView.scrollToItem(at: targetIndexPath, at: .centeredHorizontally, animated: false)
- 如果需要保留滚动动画,可先计算目标item的横向偏移量,通过
setContentOffset(_:animated:)手动实现滚动,绕开系统scrollToItem的错误计算逻辑。
方案2:滚动后主动刷新布局
- 调用
scrollToItem()后,在动画完成的时机主动触发布局校验,覆盖系统的错误偏移:
collectionView.scrollToItem(at: targetIndexPath, at: .centeredHorizontally, animated: true) // 适配iOS15的Bug修复 if #available(iOS 15.0, *), #unavailable(iOS 16.0) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { // 动画时长默认0.3s collectionView.collectionViewLayout.invalidateLayout() } }
- 也可通过自定义标记位区分代码滚动和用户手动滚动,在
visibleItemsInvalidationHandler中强制修正item的y坐标为正确的固定值,避免偏移。
方案3:绕开系统分页行为
- 不使用系统提供的
.paging类正交滚动行为,自己在UIScrollViewDelegate的scrollViewWillEndDragging(_:withVelocity:targetContentOffset:)方法中实现分页逻辑,从根本上避开该系统Bug的触发路径,该方案兼容性最好,不受系统版本迭代影响。
内容的提问来源于stack exchange,提问作者David Schmoecker
相关产品推荐
相关产品推荐

