转载

iOS横向瀑布流的封装

前段时间, 做一个羡慕, 需要使用到瀑布流! 说道瀑布流, 或许大家都不陌生, 瀑布流的实现也有很多种! 从scrollView 到 tableView 书写的瀑布流, 然后再到2012年iOS6 苹果API 新加进的collectionView进行的瀑布流封装! 确实, 不论是写起来还是用起来都要方便很多!

由于项目开发中需要使用到很像瀑布流, 本来想着懒省事, 直接搜一个第三方, 可搜了一会, 并没有搜到有关横向瀑布流的第三方! 于是就决定自己写一个吧! 里边用到的就是UICollecitionViewFlowLayout 的一个UICollectionViewLayoutAttributes 这个属性!

要明白瀑布流的原理, 写起来就会方便很多! 我下代码, 就是喜欢加多注释, 能够方便自己去找问题, 也能把当时的思路给记下来! 所以, 代码看起来, 好多绿色的中文注释, 或许对大神来说, 很弱! 但是, 能然自己读懂, 让大家读懂就够了!哈哈, 废话不多说! 直接上代码了! 思路还有实现步骤全在代码里!

.h 生命中只需要传入一个 你所需要横向瀑布流的行数, 还有一个model类的数组, model类是你自己定义的, 里边有图片的宽高,就可以了!

有什么疑问, 或者写的不对的地方, 希望提出来, 我虚心学习, 向大家探讨探讨

1 //  2 //  JF HorizontalWaterFlowLayout.h  3 //  ArtWorld  4 //  5 //  Created by laouhn on 15/10/29.  6 //  Copyright © 2015年 Jesonliu. All rights reserved.  7 //  8   9 #import <UIKit/UIKit.h> 10  11 @interface JF_HorizontalWaterFlowLayout : UICollectionViewFlowLayout 12  13 // 总行数 14 @property (nonatomic, assign) NSInteger rowCount; 15 // 商品数据数组 16 @property (nonatomic, strong) NSArray *modelList; 17  18 @end
1 //   2 //  JF HorizontalWaterFlowLayout.m   3 //  ArtWorld   4 //   5 //  Created by laouhn on 15/10/29.   6 //  Copyright © 2015年 Jesonliu. All rights reserved.   7 //   8    9 #import "JF HorizontalWaterFlowLayout.h"  10 #import "ArtCollectionViewCellModel.h"  11   12 @interface JF_HorizontalWaterFlowLayout ()  13 @property (nonatomic, assign) CGFloat remmenberW;  14   15 // 所有item的属性的数组  16 @property (nonatomic, strong) NSArray *layoutAttributesArray;  // 定义布局属性的数组, 用来存放布局item 的属性  17   18 @end  19   20 @implementation JF_HorizontalWaterFlowLayout  21 /**  22  *  布局准备方法 当collectionView的布局发生变化时 会被调用  23  *  通常是做布局的准备工作 itemSize.....  24  *  UICollectionView 的 contentSize 是根据 itemSize 动态计算出来的  25  */  26   27 - (void)prepareLayout {  28     [super prepareLayout];  29     // 根据行数 计算item的高度 所有item 的高度是一样的  30     // 内容页的高度  31     CGFloat contenHeight = self.collectionView.bounds.size.height - self.sectionInset.top - self.sectionInset.bottom;  32     // 行与行之间的距离  33     CGFloat marginY = self.minimumLineSpacing;  34     // item 的高度  35     CGFloat itemHeight = (contenHeight - marginY * (self.rowCount - 1)) / self.rowCount;  36     // 计算布局属性  37     [self computeAttributesWithItemWith:itemHeight];  38 }  39   40   41 /**  42     根据itemHeight 计算布局属性  43  */  44 - (void)computeAttributesWithItemWith:(CGFloat)itemHeight {  45     // 定义一个行宽数组 记录每一行的总宽度  46     CGFloat rowWidth[self.rowCount];  47     // 定义一个记录每一行的总item个数数组  48     NSInteger rowItemCount[self.rowCount];                      // 此处为C语言格式, 定义两个数组, 元素个数为self.rowCount, 数组类型为CGFloat 和 NSInteger  49       50     // 初始化  51     for (int i = 0; i < self.rowCount; i++) {  52         rowWidth[i] = self.sectionInset.left; // 行宽 要加上分区距离左边的距离 所以初始距离 只有分区距左边的距离  53         rowItemCount[i] = 0;                  // 初始化时, 是每一行item 的个数为零, 清空数组元素内容  54     }  55       56     // 遍历modelList 数组, 计算相关属性  57     NSInteger index = 0;  // 定义索引变量, 初始值为零  58       59     NSMutableArray *attributesArray = [NSMutableArray arrayWithCapacity:self.modelList.count];  // 定义一个可变存储布局属性的数组, 并开辟空间大小为self.modelList.count个空间  60       61     // 遍历self.modelList 数组, 得到model 类, 获取属性  62     for (ArtCollectionViewCellModel *model in self.modelList) {  63   64         // 创建路径, 记录item 所在分区分区和位置  65         NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];  66           67         // 根据路径创建对应的布局属性  68         UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];  69           70         // 找出最短的行号  71         NSInteger row = [self shortestRow:rowWidth];  72           73         // 追加在最短行, 使记录每一行的总item个数数组中最短行对应的元素个数 +1  74         rowItemCount[row]++;  75           76         // X值  77         CGFloat itemX = rowWidth[row]; // 最短行的总宽度  78           79         // Y值  80         CGFloat itemY = (itemHeight + self.minimumLineSpacing) * row + self.sectionInset.top; // 计算, 注意逻辑性  81           82         // 等比例缩放 计算item 的宽度  83         CGFloat itemW = ([model.worksWidth floatValue] / [model.worksHeight floatValue]) * itemHeight; // 显示宽 / 显示高 = 实际宽 / 实际高  84         // 赋给布局属性的frame  85         attributes.frame = CGRectMake(itemX, itemY, itemW, itemHeight);  86   87         // 添加到布局属性的数组中  88         [attributesArray addObject:attributes];  89           90         // 使列宽增加, 增量为item 自身的宽度, 加上两个item 之间的最小距离  91         rowWidth[row] += itemW + self.minimumInteritemSpacing;  92           93         // 是索引+1  94         index++;  95     }  96       97       98 //     找出 最宽行的行号  99     NSInteger row = [self widthestRow:rowWidth]; 100      101     self.remmenberW =  rowWidth[row]; 102      103     // 根据最宽行设置itemSize 使用总宽度的平均值 104     CGFloat itemW = (rowWidth[row] - self.minimumInteritemSpacing * rowItemCount[row]) / rowItemCount[row]; 105      106     self.itemSize = CGSizeMake(itemW, itemHeight); 107      108     // 给属性数组设置数值 109     self.layoutAttributesArray = attributesArray.copy; 110      111 } 112  113 // 找出rowWidth 数组中最短行号 追加数据的时候 追加在最短行中 114 - (NSInteger)shortestRow:(CGFloat *)rowWidth { 115     CGFloat max = CGFLOAT_MAX; 116     NSInteger row = 0; 117     for (int i = 0; i < self.rowCount; i++) { 118         if (rowWidth[i] < max) { 119             max = rowWidth[i]; 120             row = i; 121         } 122     } 123     return row;  // 返回最短的行 124 } 125  126 // 找出rowWidth 数组中最宽的行号 127 - (NSInteger)widthestRow:(CGFloat *)rowWidth { 128     CGFloat min = 0; 129     NSInteger row = 0; 130     for (int i = 0; i < self.rowCount; i++) { 131         if (rowWidth[i] > min) { 132             min = rowWidth[i]; 133             row = i; 134         } 135     } 136     return row; 137 } 138  139  140 /** 141  *  跟踪效果:当到达要显示的区域时 会计算所有显示item的属性 142  *           一旦计算完成 所有的属性会被缓存 不会再次计算 143  *  @return 返回布局属性(UICollectionViewLayoutAttributes)数组 144  */ 145 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 146      147     // 直接返回计算好的布局属性数组 148     return self.layoutAttributesArray; 149 } 150  151 // 重写此方法, 改变collectionView的contentSize 152 - (CGSize )collectionViewContentSize{ 153     return CGSizeMake(self.remmenberW, self.collectionView.bounds.size.height); 154 } 155  156  157  158  159 @end
正文到此结束
Loading...