瀑布流的实现方法
- 第一种方法:在底部放一个scrollView,根据内容的大小定制view的大小,在scrollView上面进行排列,因为展示的内容太多,所以最好让view进行复用,这样的方法还是挺复杂的。
- 第二种方法:在iOS6之后有了流布局之后,由系统帮你实现cell复用,工作就简单了很多。
今天主要说的就是第二种方法,实现瀑布流的思路及做简单的封装
- 因为瀑布流也是一种布局,所以我们不能去继承流布局本身的流水布局,因为那种布局每个格子的大小都是固定的。所以我们要继承
UICollectionViewLayout
。 - 我们需要实现的方法
- (void)prepareLayout
每一次刷新对设置进行初始化,去清除之前计算的数据
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
返回每一个cell的属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
设置每一个cell对应的属性
- (CGSize)collectionViewContentSize
返回内容的高度,内容的高度根据最后一行最长的一列计算 - 我们需要针对数据源的高去写cell的高,因为瀑布流是长短不一的,所以我们需要计算出每一行最短的那一列
下面贴出动态计算cell高度的代码吧
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGFloat width = (self.collectionView.frame.size.width - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
CGFloat height = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:width];
NSInteger minColumnCount = 0;
CGFloat minColunmnMaxY = [self.columnHeights[0] floatValue];
for (NSInteger i = 1; i < self.columnCount; ++i)
{
CGFloat columnHeight = [self.columnHeights[i] floatValue];
if (minColunmnMaxY > columnHeight)
{
minColunmnMaxY = columnHeight;
minColumnCount = i;
}
}
CGFloat x = self.edgeInsets.left + minColumnCount * (width + self.columnMargin);
CGFloat y = minColunmnMaxY;
if (y != self.edgeInsets.top)
{
y += self.rowMargin;
}
attributes.frame = CGRectMake(x, y, width, height);
self.columnHeights[minColumnCount] = @(CGRectGetMaxY(attributes.frame));
CGFloat columnHeight = [self.columnHeights[minColumnCount] floatValue];
if (self.contentHeight < columnHeight)
{
self.contentHeight = columnHeight;
}
return attributes;
}
- 这里已经计算出了最短的列和最长的列,所以每一个cell该怎么放,以及整个UICollectionView的内容大小也已经计算出来
今天就到这里吧,感觉写的也不太满意,哪里有问题可以指出来。