iOS自定义collection view的page size(width/height)分页效果

前言

想必大家工作中或多或少会遇到下图样式的UI需求吧

像这种cell长度不固定,并且还能实现的分页效果UI还是很常见的

实现

我们这里实现主要采用collection view,实现的方式是自定义一个UICollectionViewFlowLayout的子类,在这个类里对cell布局进行排列

  • 当出现page size小于collection view的size的时候,可以使用ZLCollectionFreePageLayout一下子就实现分页效果
  • 并且不需要设置属性collectionView.isPagingEnabled = true ,只要设置了layout为ZLCollectionFreePageLayout,就可以自动实现这种效果

主要代码如下:

swift 复制代码
open override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
        guard let collectionView = collectionView else {
            return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity)
        }
        
        var pWOrH: CGFloat = 0
        var contentOffsetXOrY: CGFloat = 0
        var collectionViewContentWOrH: CGFloat = 0
        var velocityXOrY: CGFloat = 0
        
        if scrollDirection == .horizontal {
            pWOrH = (pageWOrH == 0 ? collectionView.frame.width : pageWOrH) + minimumLineSpacing
            contentOffsetXOrY = collectionView.contentOffset.x
            collectionViewContentWOrH = collectionViewContentSize.width
            velocityXOrY = velocity.x
        } else {
            pWOrH = (pageWOrH == 0 ? collectionView.frame.height : pageWOrH) + minimumInteritemSpacing
            contentOffsetXOrY = collectionView.contentOffset.y
            collectionViewContentWOrH = collectionViewContentSize.height
            velocityXOrY = velocity.y
        }
        
        let originalPage = contentOffsetXOrY / pWOrH
        var nextPage = (velocityXOrY > 0) ? ceil(originalPage) : floor(originalPage)
        if (nextPage + 1.0) * pWOrH > collectionViewContentWOrH { nextPage -= 1.0 }
        
        let currentPage = (velocityXOrY > 0) ? floor(originalPage) : ceil(originalPage)
        let pannedLessThanOnePage = abs(1 + currentPage - originalPage) > 0.5
        let flicked = abs(velocityXOrY) > 0.01
        
        var newProposedContentOffset = proposedContentOffset
        if !(pannedLessThanOnePage && flicked) {
            nextPage = round(originalPage)
        }
        
        newProposedContentOffset.x = nextPage * pWOrH
        
        return newProposedContentOffset
    }
  • 在使用的时候,只需要将collection.collectionViewLayout的属性设置为我们自定义的layout对象,具体代码如下面的示例代码:
swift 复制代码
private lazy var collectionView: UICollectionView = {
  // 实例化一个ZLCollectionLeftLayout对象
  let defaultLayout = ZLCollectionFreePageLayout()
  
  // 自定义page width或者page height
  defaultLayout.pageWOrH = 200.0
  defaultLayout.minimumLineSpacing = 10.0
  defaultLayout.minimumInteritemSpacing = 10.0
  defaultLayout.scrollDirection = .vertical
  defaultLayout.sectionInset = UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
  // 设置collection view的layout为ZLCollectionFreePageLayout
  let collectionView = UICollectionView(frame: .zero, collectionViewLayout: defaultLayout)
  collectionView.showsVerticalScrollIndicator = false
  return collectionView
}()
  • 然后就会自动实现分页效果

  • 并且不需要 设置属性collectionView.isPagingEnabled = true

开源代码地址

代码开源到github上了,可以直接拿来使用

开源代码地址

相关推荐
天桥吴彦祖1 天前
判断iOS如何监听手机屏幕是否锁屏
ios
东坡肘子2 天前
SPI 加入 Apple,Swift 迈向自举 -- 肘子的 Swift 周报 #142
人工智能·swiftui·swift
敲代码的鱼2 天前
PDF 预览与签名批注写回 支持安卓 iOS 鸿蒙 UTS插件
android·前端·ios
时光足迹2 天前
uni-app 视频通话实战:康复师与患者视频问诊的 6 个致命 Bug 与解决方案
android·ios·uni-app
时光足迹2 天前
JPush UniApp UTS 插件完全参考手册:API、事件与厂商通道一网打尽
vue.js·ios·uni-app
时光足迹2 天前
极光推送全攻略(下):uni-app 代码实现与 iOS 排查实战
vue.js·ios·uni-app
时光足迹2 天前
极光推送全攻略(上):被iOS证书折磨了三天,我写了一份前端也能看懂的避坑指南
前端·ios·uni-app
编程范式4 天前
SwiftUI 中图片如何适配可用空间
ios
songgeb6 天前
启发式 UI 自动化:从线性剧本到每步读屏决策
ios·测试
东坡肘子9 天前
Swift 还让你 Excited 吗?-- 肘子的 Swift 周报 #141
人工智能·swiftui·swift