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上了,可以直接拿来使用

开源代码地址

相关推荐
sakiko_11 小时前
OC基础语法(与Swift对比)-1
开发语言·ios·objective-c·swift
未来猫咪花11 小时前
Everything is ViewModel:让状态管理回到对象世界
android·flutter·ios
xy345311 小时前
Axure9.0 中继器遮罩的核心应用场景(精准适配列表交互)
前端·ui·html·原型·产品设计·axure9.0
Crazy_MT12 小时前
不越狱,iPhone 为什么也能安装任意 IPA?聊聊 iLoader、SideStore 和 LiveContainer 的原理
ios·开源
skr爱码士16 小时前
15_国际化和本地化:tr()、ts 文件、QM 文件、多语言切换
c++·qt·ui·客户端
JoyCong199818 小时前
从iPhone Ultra到ToDesk:折叠大屏时代的效率革命,硬件只是开始
大数据·运维·ios·智能手机·iphone·远程工作·远程操作
2501_9160074718 小时前
Flutter与游戏App加固避坑指南:如何为混合开发与高交互应用选对安全方案?
安全·flutter·游戏·ios·小程序·uni-app·iphone
贝格前端工场19 小时前
AI在生产制造企业的六大成熟落地场景(可量产、可验收、非噱头)
大数据·ui·前端开发
2501_9160088919 小时前
Flutter 开发 iOS,项目打包成 IPA,命令与免 Xcode两种方法
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程