我是模仿上面的代码自己写了一份,实现的是简单的瀑布流:
就是把UICollectionView分成三列,由数组保存每一列的高度,然后每次设置UICollectionViewLayoutAttributes的时候,获取最短一列,计算出图片的size,然后添加到最短一列上面。
注:这里是没有实现横向的瀑布流
ViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"WaterFall Flow";
// 设置 UICollectionViewLayout
WaterFallLayout *flowLayout = [[WaterFallLayout alloc] init];
flowLayout.delegate = self;
CGFloat width = ([UIScreen mainScreen].bounds.size.width - 40) / 3;
flowLayout.itemSize = CGSizeMake(width, width);
// 间隙
flowLayout.insertItemSpacing = 10;
// 内边距
flowLayout.sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
// 列数
flowLayout.numberOfColumn = 3;
self.flowCV.collectionViewLayout = flowLayout;
// Register Cell
UINib *cellNib = [UINib nibWithNibName:@"FlowCollectionViewCell" bundle:[NSBundle mainBundle]];
[self.flowCV registerNib:cellNib forCellWithReuseIdentifier:@"CELL"];
[self parserJsonData];
}
#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [self.itemArray count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
FlowCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CELL" forIndexPath:indexPath];
FlowModel *model = self.itemArray[indexPath.item];
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:model.thumbURL]];
return cell;
}
WaterFallLayout.m
@interface WaterFallLayout()
// 所有Item的数量
@property (nonatomic,assign) NSUInteger numberOfItems;
// 这是一个数组,保存每一列的高度
@property (nonatomic,strong) NSMutableArray *columnHeights;
// 这是一个数组,数组中保存的是一种类型,这种类型决定item的位置和大小。
@property (nonatomic,strong )NSMutableArray *itemAttributes;
// 获取最长列索引
- (NSInteger)indexForLongestColumn;
// 获取最短列索引
- (NSInteger)indexForShortestColumn;
@end
#pragma mark - UICollectionViewLayout
- (void)prepareLayout{
[super prepareLayout];
// 初始化所有高度
for (int i = 0; i < self.numberOfColumn; i++) {
self.columnHeights[i] = @(self.sectionInsets.top);
}
// 获取item数量
self.numberOfItems = [self.collectionView numberOfItemsInSection:0];
// 循环计算每一个item的x,y,width,height
for (int i = 0; i < self.numberOfItems; i++) {
/*
这里分成三列,每计算一个Item,就取高度最短的那一列,放图片上去(这里图片宽度一致),依次叠加
*/
// 获取最短列
NSInteger shortIndex = [self indexForShortestColumn];
// 获取最短列高度
CGFloat shortestH = [self.columnHeights[shortIndex] floatValue];
// x
CGFloat detalX = self.sectionInsets.left + (self.itemSize.width + self.insertItemSpacing) * shortIndex;
// y
CGFloat detalY = shortestH + self.insertItemSpacing;
// h
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
CGFloat itemHeight = 0;
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(heightForItemIndexPath:)]){
itemHeight = [self.delegate heightForItemIndexPath:indexPath];
}
// 保存item frame属性的对象
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attr.frame = CGRectMake(detalX, detalY, self.itemSize.width, itemHeight);
// 放入数组
[self.itemAttributes addObject:attr];
// 更新列高度
self.columnHeights[shortIndex] = @(detalY + itemHeight);
}
}
// 计算contentSize
- (CGSize)collectionViewContentSize{
// 获取最高列
NSInteger longestIndex = [self indexForLongestColumn];
CGFloat longestH = [self.columnHeights[longestIndex] floatValue];
// 计算contentSize
CGSize contentSize = self.collectionView.frame.size;
contentSize.height = longestH + self.sectionInsets.bottom;
return contentSize;
}
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{
return self.itemAttributes;
}
实现之后的效果图: