You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 00:44:57