新建文件继承自UICollectionViewLayout .h内容如下:

@class WaterFlowLayout;
@protocol WaterFlowLayoutDelegate <NSObject>//使用delegate取得每一个Cell的高度
- (CGFloat)waterFlow:(WaterFlowLayout *)layout heightForCellAtIndexPath:(NSIndexPath *)indexPath;@end@interface WaterFlowLayout : UICollectionViewLayout//声明协议
@property (nonatomic, weak) id <WaterFlowLayoutDelegate> delegate;
//确定列数
@property (nonatomic, assign) NSInteger colum;
//确定内边距
@property (nonatomic, assign) UIEdgeInsets insetSpace;
//确定每个cell之间的距离
@property (nonatomic, assign) NSInteger distance;@end
复制代码

.m实现内容如下:

@interface WaterFlowLayout ()
//存储列高的数组
@property (nonatomic, strong) NSMutableArray *columHeightArr;
//存储所有cell的尺寸信息
@property (nonatomic, strong) NSMutableArray *cellFrameArr;@end@implementation WaterFlowLayout//colum的set方法
- (void)setColum:(NSInteger)colum{if (_colum != colum) {_colum = colum;//将之前的布局信息失效,重新布局[self invalidateLayout];}
}//distance的set方法
- (void)setDistance:(NSInteger)distance{if (_distance != distance) {_distance = distance;[self invalidateLayout];}
}//insetSpace的set方法
- (void)setInsetSpace:(UIEdgeInsets)insetSpace{if (!UIEdgeInsetsEqualToEdgeInsets(_insetSpace, insetSpace)) {_insetSpace = insetSpace;[self invalidateLayout];}
}//自定义layout需要重写下面的几个方法
//准备布局,将item的位置信息计算出来
- (void)prepareLayout{//将位置信息和高度信息的数组实例化[self initDataArray];//初始化每一列的初始高度[self initColumHeightArray];//初始化计算出全部cell的高度,并且存入数组[self initAllCellHeight];
}//将位置信息和高度信息的数组实例化
- (void)initDataArray{//记录当前每一列的高度,所以我们只需要列数的空间就够了。_columHeightArr = [NSMutableArray arrayWithCapacity:_colum];//记录所有cell的尺寸信息_cellFrameArr = [NSMutableArray arrayWithCapacity:0];
}//初始化每一列的初始高度
- (void)initColumHeightArray{for (int i = 0; i < _colum; i++) {[_columHeightArr addObject:@(_insetSpace.top)];}
}//初始化计算出全部cell的高度,并且存入数组
- (void)initAllCellHeight{//拿出第一组的全部cell的数量NSInteger allCellNumber = [self.collectionView numberOfItemsInSection:0];//取得整个collectionView的宽度CGFloat totalWidth = self.collectionView.frame.size.width;//取得一行中Cell的总宽度CGFloat itemAllWidth = totalWidth - _insetSpace.left - _insetSpace.right - _distance * (_colum - 1);//取得每一个cell的宽度CGFloat width = itemAllWidth/_colum;//循环计算每一个cell的高度并且将位置信息添加到数组中for (int i = 0; i < allCellNumber; i++) {//拿到当前的列的信息NSInteger currentColum = [self getShortColum];//x偏移就是用当前的列去乘以宽度和间距,并且加上内边距CGFloat xOffset = _insetSpace.left + currentColum * (width + _distance);//制造索引路径NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];//取得y偏移CGFloat yOffset = [[_columHeightArr objectAtIndex:currentColum] floatValue] + _distance;//取得高度,由实现协议者提供CGFloat height = 0.f;if (_delegate && [_delegate respondsToSelector:@selector(waterFlow:heightForCellAtIndexPath:)]) {height = [_delegate waterFlow:self heightForCellAtIndexPath:indexPath];}//整理cell的尺寸信息CGRect frame = CGRectMake(xOffset, yOffset, width, height);//attributes是用来存储当前indexPath的cell的位置信息的UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];attributes.frame = frame;//将位置信息添加到cell尺寸数组中[_cellFrameArr addObject:attributes];//改变当前列的高度_columHeightArr[currentColum] = @(frame.size.height + frame.origin.y);}
}//取得当前cell的尺寸
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{return [_cellFrameArr objectAtIndex:indexPath.item];
}//根据rect去找出需要布局的cell的位置信息
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{//用来存储可以展示的cell的位置信息NSMutableArray *temp = [NSMutableArray arrayWithCapacity:0];for (UICollectionViewLayoutAttributes *attributes in _cellFrameArr) {//如果取出的位置信息,在rect的范围内,就将这个位置信息,装入数组中。if (CGRectIntersectsRect(attributes.frame, rect)) {[temp addObject:attributes];}}return temp;
}//指定collection的contentSize
- (CGSize)collectionViewContentSize{//内容宽度指定为collectionView的宽度(横向不发生滚动)CGFloat width = self.collectionView.frame.size.width;//取出最长的列,将其高度定位长度CGFloat height = [self getLongColum];return CGSizeMake(width, height);
}- (CGFloat)getLongColum{//记录当前最长的列号__block NSInteger currentColum = 0;//假设最长的列高度为0__block CGFloat longHeight = 0;//枚举数组中的元素[_columHeightArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {if ([obj floatValue] > longHeight) {longHeight = [obj floatValue];currentColum = idx;}}];return longHeight + _insetSpace.bottom;
}//取得最短的列
- (NSInteger)getShortColum{//记录当前最短的列号__block NSInteger currentColum = 0;//假设最短的列高度为float的最大值__block CGFloat shortHeight = MAXFLOAT;//枚举数组中的元素[_columHeightArr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {if ([obj floatValue] < shortHeight) {shortHeight = [obj floatValue];currentColum = idx;}}];return currentColum;
}@end
复制代码

附:我的博客地址

iOS 瀑布流布局实现详解相关推荐

  1. Cisco ××× 完全配置指南-连载-IOS ×××阶段2连接详解

    Cisco ××× 完全配置指南-连载-IOS ×××阶段2连接详解 详细配置见附件 转载于:https://blog.51cto.com/xuanbo/151764

  2. IOS学习之UINavigationController详解与使用(一)添加UIBarButtonItem

    转:http://blog.csdn.net/totogo2010/article/details/7681879 1.UINavigationController导航控制器如何使用 UINaviga ...

  3. iOS里面MVC模式详解

    iOS里面MVC模式详解 MVC是IOS里面也是很多程序设计里面的一种设计模式,M是model,V是view,C是controller.MVC模式在ios开发里面可谓是用得淋漓尽致. 以下是对斯坦福大 ...

  4. iOS开发证件要点详解

    iOS开发证书要点详解 引言 关于开发证书配置(Certificates&Identifiers&Provisioning Profiles),相信做iOS开发的同学没少被折腾.对于一 ...

  5. iOS APP上架流程详解

    iOS APP上架流程详解 青葱烈马 2016.04.28  前言:作为一名 iOS 开发工程师, APP 的上架是必备技能. iOS 上架的流程主要可以简单总结为: 一个包,两个网址,三个证书, 一 ...

  6. iOS中ImageIO框架详解与应用分析

    2019独角兽企业重金招聘Python工程师标准>>> iOS中ImageIO框架详解与应用分析 一.引言 ImageIO框架提供了读取与写入图片数据的基本方法,使用它可以直接获取到 ...

  7. iOS动画-CAAnimation使用详解

    理解了隐式动画后,显式动画就更加通俗易懂了.区别于隐式动画的特点,显式动画就是需要我们明确指定类型.时间等参数来实现效果的动画.除此之外,我们也可以创建非线性动画,比如沿着任意一条曲线运动等: 我们平 ...

  8. [置顶] iOS中 支付宝钱包详解/第三方支付

    [置顶] iOS中 支付宝钱包详解/第三方支付 韩俊强的博客 每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 一.在app中成功完成支付宝支付的过程 1.申请支付 ...

  9. Flutter开发之iOS后台定位开发详解

    Flutter开发之iOS后台定位开发详解 需求目的 开发一个功能持续获取用户的位置发送给后端,PC端会根据后端传来的移动端发送的位置信息,来绘制使用者的运动轨迹. 实现需求 是否实现 后台定位 ✅ ...

最新文章

  1. OSPF 提升 一 ----基础
  2. 图灵71年前就已提出神经网络!《智能机器》再掀热议却一生未发表
  3. com.microsoft.sqlserver.jdbc.SQLServerException: 索引 1 超出范围
  4. 昆明理工大学2017计算机考研题,2017年昆明理工大学现代农业工程学院341农业知识综合三[专业硕士]之计算机网络考研题库...
  5. em算法 实例 正态分布_【机器学习】EM算法详细推导和讲解
  6. [数论]莫比乌斯反演1
  7. Linux 给新用户授予、设置Tomcat目录的使用权限
  8. 牛客网数据库SQL实战答案解析上篇
  9. 自动化系统计算机网络期末考试题,模拟试卷_计算机网络试题B-自动化-孙璐
  10. UML教程2:用例图
  11. linux安装vim
  12. AD转换原理与方案设计(包含原理图、PCB和BOM表)
  13. 制作电脑显示器流光溢彩
  14. 你在读文学作品的时候也许从来没考虑这些问题
  15. clear linux
  16. 云计算技术基础复习知识点
  17. unity小球酷跑项目
  18. C语言 求n的阶乘及阶乘和
  19. STATA 森林图 基于OR值和CI直接画的
  20. 蓝桥杯之未名湖边的烦恼-递归极简版(c++实现)

热门文章

  1. (计算机组成原理)第二章数据的表示和运算-第四节1:算数逻辑单元和电路基本知识以及基本逻辑运算和全加器还有串行、并行加法器
  2. SendMessage
  3. Linux日常运维管理技巧(二)Linux防火墙:你可以ping别人,别人ping不了你、转发、代理
  4. PHP-FPM Fastcgi 未授权访问漏洞(端口9000)
  5. distribution was not found and is required by the application错误
  6. golang 生成随机数
  7. C/C++获取指定网口的IP地址
  8. linux 各系统防火墙操作
  9. [Java]LeetCode138. 复制带随机指针的链表 | Copy List with Random Pointer
  10. 一次SSIS Package的调试经历