iOS17下UICollectionView.scrollToItem滚动偏移异常求助
iOS 17 下 UICollectionView scrollToItem 滚动位置异常(分页启用时)
问题重现
在 iOS 17 设备搭配 Xcode 15 + macOS 14 的环境中,调用 UICollectionView.scrollToItem(at:at:animated:) 方法时会出现过度向上滚动的异常,但该问题在 iOS 16 及以下系统中不存在。
对应的布局配置代码:
private let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) view.addSubview(collectionView) collectionView.snp.makeConstraints { make in make.left.right.top.bottom.equalToSuperview() } let collectionLayoutConfig = UICollectionViewCompositionalLayoutConfiguration() collectionLayoutConfig.scrollDirection = .horizontal let layout = UICollectionViewCompositionalLayout(sectionProvider: { section, _ in func getSection(cellCount: Int, extraInterGroupSpacing: Bool = false) -> NSCollectionLayoutSection { let cellSpacing = 10 let cellInset = 24 let cellLength = UICollectionView.cellLength(cellCount: cellCount, colViewLength: TT.screenWidth, cellSpacing: cellSpacing, inset: cellInset) let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(cellLength), heightDimension: .absolute(cellLength)) let item = NSCollectionLayoutItem(layoutSize: itemSize) let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(cellLength)) let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item]) group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0) group.interItemSpacing = NSCollectionLayoutSpacing.fixed(10) let section = NSCollectionLayoutSection(group: group) section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 24, bottom: extraInterGroupSpacing ? 30 : 24, trailing: 24) section.interGroupSpacing = extraInterGroupSpacing ? 20 : 10 section.orthogonalScrollingBehavior = .continuous return section } switch section { case 0: return getSection(cellCount: 7) case 1: return getSection(cellCount: 4, extraInterGroupSpacing: true) default: return getSection(cellCount: 4) } }, configuration: collectionLayoutConfig) collectionView.setCollectionViewLayout(layout, animated: true) collectionView.showsHorizontalScrollIndicator = false collectionView.register(cellType: CutoutCell.self) collectionView.register(cellType: CutoutCellAnimated.self) collectionView.delegate = self collectionView.dataSource = self collectionView.backgroundColor = .clear collectionView.contentInsetAdjustmentBehavior = .automatic collectionView.isPagingEnabled = true
触发异常的调用代码:
scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
已确认的解决方案
将 collectionView.isPagingEnabled 设置为 false 后,滚动位置异常问题直接消失。
替代方案(需保留分页时)
这个问题是 iOS 17 中 UICollectionView 原生分页功能与 scrollToItem 方法的兼容 Bug,社区里已有不少开发者反馈。如果业务必须保留分页,可以试试这些替代方案:
- 自定义分页逻辑:通过
UIScrollViewDelegate的scrollViewDidEndDecelerating、scrollViewWillEndDragging等代理方法,手动计算目标分页的偏移量,调用setContentOffset(_:animated:)完成滚动 - 改用
scrollRectToVisible:先获取目标 cell 的 frame(需转换为 collectionView 的坐标系),再调用collectionView.scrollRectToVisible(targetFrame, animated: true)实现精准滚动 - 延迟执行滚动:在布局更新完成后(比如
viewDidLayoutSubviews或数据刷新完成的回调里),延迟 0.1~0.2 秒调用scrollToItem,避免布局未稳定时触发滚动
内容的提问来源于stack exchange,提问作者Austin Huang
相关产品推荐
相关产品推荐

