UICollectionView自定义pagingEnabled翻页区域

UICollectionView自定义pagingEnabled翻页区域
最新回答
忘记心痛回忆

2020-07-14 13:16:58

这个标题挺难起的:

直接看效果:

比较一下直接设置 collectionView.pagingEnabled = YES 的效果:

源码在 GitHub ,item的宽度和间距使用宏定义,方便修改

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;

首先, proposedContentOffset 参数的含义是系统根据用户的滑动手势计算出来的将要滑动到的目标位置。
我们可以在 UICollectionViewFlowLayout 的子类里重写这个方法,根据系统计算出来的期望目标位置 proposedContentOffset 和滑动速度 velocity ,自定义滑动位置。

将item有关参数设置为宏,方便修改

在这个方法里,需要计算:

重写这个方法就可以指定滑动停止的位置,我的计算思路是先根据用户的滑动手势,判断是向前翻页还是向后翻页,向后翻页则目标页码 index = _currentIndex + 1 。 翻页时,实际的页面宽度是每页刚好可以完整展示的最多个item的宽度,即 _pageCapacity * (kItemWidth + kPaddingMid) ,那么x轴目标偏移就是 point.x = 目标页码 * 每页实际宽度
这里需要知道滑动前当前的页码 _currentIndex , 我是通过 UIScrollViewDelegate 的代理方法取到用户将要滑动时的x轴偏移计算的

文章开头已说明,设置 scrollView.pagingEnabled = YES 达不到我们的目标,本文介绍的方案里需要设置 scrollView.pagingEnabled = NO ,否则上面函数中自定义的滑动位置不起作用

设置 scrollView.decelerationRate = UIScrollViewDecelerationRateFast; ,滑动效果基本接近系统pagingEnabled

运行起来后简单测试,需求基本满足了

从打印日志发现从第一页翻到第二页,然后(未等滑动完全停止)继续滑动时,x轴偏移量比目标偏移量小几个像素,即滑动还没有完全结束。由于当前页的index是通过x轴偏移量取整求商得到的,这几个像素的差异会导致index比预期小1

在计算当前的页码 _currentIndex 时,用一个item的宽度补偿x轴偏移量,由于 kItemWidth 恒小于 _pageCapacity * (kItemWidth + kPaddingMid) ,这种补偿不会造成页面index加1,是安全的