在上一篇博文中,我们展示了如何使用 uicollectionview 实现卡片轮播效果。有网友反馈了一个问题:当 item 的宽度与屏幕宽度一致时,滚动效果正常,但当 item 宽度小于屏幕宽度时,会出现遮挡的 bug。如何解决这个问题呢?

这个问题确实存在,因为 UICollectionView 有一个分页属性 isPagingEnabled,当设置为 true 时,每次滚动的位移量等于屏幕宽度;当设置为 false 时(默认值),滚动没有分页效果。有人可能会问,UICollectionView 是否只能按照屏幕大小进行分页?答案当然是否定的。
要实现自定义的滚动分页,我们需要依赖 UICollectionViewFlowLayout。在 UICollectionViewFlowLayout 中,有一个可以重写的函数:
func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint // return a point at which to rest after scrolling - for layouts that want snap-to-point scrolling behavior
这个函数的返回值决定了 UICollectionView 停止滚动时的偏移量。我们可以通过重写这个函数来实现自定义的分页滚动。重写这个函数的逻辑如下:
定义一个 CGPoint 来记录最新滚动的偏移坐标。定义两个值,分别为 UICollectionView 可滚动的最大偏移量和最小偏移量(即 0)。每次滚动停止时都会调用上述函数 func targetContentOffset(…),这个函数有一个参数 proposedContentOffset 记录了滚动的目标位移坐标。通过这个坐标和记录的上次滚动的坐标,可以判断出是向左滚动还是向右滚动。如果两个坐标的水平方向相减的绝对值大于某个固定值(例如 item 宽度的八分之一),则可以判断发生了分页,然后通过 proposedContentOffset 位移坐标和 item 的宽度大小来计算出当前滚动的页码;如果小于那个固定值,则不发生分页。最后记录最新的偏移坐标,然后返回 UICollectionView 停止滚动时的偏移量。
言语空洞,让我们看代码,实现如下:
火龙果写作
用火龙果,轻松写作,通过校对、改写、扩展等功能实现高质量内容生产。
106 查看详情
class RowStyleLayout: UICollectionViewFlowLayout { private var lastOffset: CGPoint! override init() { super.init() lastOffset = CGPoint.zero } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } // 初始化 override func prepare() { super.prepare() self.collectionView?.decelerationRate = .fast } // 这个方法的返回值,决定了 CollectionView 停止滚动时的偏移量 override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { // 分页的 width let pageSpace = self.stepSpace() let offsetMax: CGFloat = self.collectionView!.contentSize.width - (pageSpace + self.sectionInset.right + self.minimumLineSpacing) let offsetMin: CGFloat = 0 // 修改之前记录的位置,如果小于最小的contentsize或者最大的contentsize则重置值 if lastOffset.x offsetMax { lastOffset.x = offsetMax } // 目标位移点距离当前点距离的绝对值 let offsetForCurrentPointX: CGFloat = abs(proposedContentOffset.x - lastOffset.x) let velocityX = velocity.x // 判断当前滑动方向,向左 true, 向右 false let direction: Bool = (proposedContentOffset.x - lastOffset.x) > 0 var newProposedContentOffset: CGPoint = CGPoint.zero if (offsetForCurrentPointX > pageSpace/8.0) && (lastOffset.x >= offsetMin) && (lastOffset.x CGFloat { return self.itemSize.width + self.minimumLineSpacing }}
运行效果如下:

至此,本文结束。按照惯例,文章末尾会提供 demo 工程的地址。
以上就是使用 UICollectionView 实现分页滑动效果的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/452309.html
微信扫一扫
支付宝扫一扫