调整scrollViewWillEndDragging适配UICollectionView横向压缩后的索引计算问题
问题根因
你遇到的索引计算错误本质是两个原因导致的:
- 强制
Int类型转换会直接截断浮点数值的小数部分,当collectionView宽度不是整数、或滑动偏移存在浮点误差时,会出现计算偏差 - 系统默认的
isPagingEnabled分页机制是基于scrollView自身bounds尺寸计算,当你自定义对齐逻辑时默认分页会引入额外偏移干扰
修复步骤
1. 调整collectionView初始化配置
在你的myCollection懒加载代码中,将isPagingEnabled改为false,避免系统默认分页逻辑干扰自定义对齐:
routine.isPagingEnabled = false
2. 重写scrollViewWillEndDragging逻辑
使用四舍五入处理索引计算,同时可以手动修正滑动结束的偏移量保证对齐准确:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { let cellWidth = myCollection.frame.width // 用四舍五入避免截断误差,得到准确的页码索引 let targetPage = round(targetContentOffset.pointee.x / cellWidth) let navigatedTo = Int(targetPage) // 可选:修正目标偏移量,确保滑动结束后cell刚好对齐collectionView边界 targetContentOffset.pointee = CGPoint(x: targetPage * cellWidth, y: targetContentOffset.pointee.y) // 此处可正常使用navigatedTo索引 print("当前选中cell索引:\(navigatedTo)") }
可选扩展:实现cell居中对齐效果
如果需要实现滑动结束后cell始终居中显示在屏幕上,可以在collectionView布局初始化时增加sectionInset配置:
// 计算左右边距,让cell居中显示在屏幕中 let screenWidth = UIScreen.main.bounds.width let sidePadding = (screenWidth - myCollection.frame.width) / 2 routineLayout.sectionInset = UIEdgeInsets(top: 0, left: sidePadding, bottom: 0, right: sidePadding)
对应的索引计算逻辑调整为基于cell中心位置计算即可:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { let cellWidth = myCollection.frame.width let targetCenterX = targetContentOffset.pointee.x + myCollection.bounds.width / 2 let targetPage = round(targetCenterX / cellWidth) let navigatedTo = Int(targetPage) // 修正偏移让cell居中 let correctedX = targetPage * cellWidth - (myCollection.bounds.width - cellWidth) / 2 targetContentOffset.pointee = CGPoint(x: correctedX, y: targetContentOffset.pointee.y) }
内容的提问来源于stack exchange,提问作者angryip
相关产品推荐
相关产品推荐

