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

开源代码地址

相关推荐
sg_knight21 小时前
设计模式实战:状态模式(State)
python·ui·设计模式·状态模式·state
黄思搏21 小时前
基于标注平台数据的 Unity UI 自动化构建工作流设计与工程实践
ui·unity·蓝湖·vectoui
用户223586218201 天前
WebKit WebPage API 的引入尝试与自研实现
ios
小樱花的樱花1 天前
1 项目概述
开发语言·c++·qt·ui
啦啦啦!1 天前
ChatGPT和Gemini的接入和封装
人工智能·ios·chatgpt
2301_822703201 天前
开源鸿蒙跨平台Flutter开发:跨端图形渲染引擎的类型边界与命名空间陷阱:以多维雷达图绘制中的 dart:ui 及 StrokeJoin 异常为例
算法·flutter·ui·开源·图形渲染·harmonyos·鸿蒙
报错小能手1 天前
ios开发方向——swift并发进阶核心 async/await 详解
开发语言·ios·swift
开心就好20251 天前
HTTPS超文本传输安全协议全面解析与工作原理
后端·ios
牛马1111 天前
Flutter iOS 权限配置完整指南(定位权限)
flutter·ios
A_QXBlms1 天前
多账号轮询架构 — 利用企销宝iPad协议突破单账号群发次数限制
ios·架构·ipad