UICollectionView
瀑布流实现思路
创建collectionView,设置代理,注册cell
// 创建布局 WZWaterfallLayout *layout = [[WZWaterfallLayout alloc] init]; // 设置代理 layout.delegate = self; //创建collectionView UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout]; collectionView.backgroundColor = [UIColor whiteColor]; collectionView.dataSource = self; [self.view addSubview:collectionView];
自定义布局,继承自纯净的UICollectionViewLayout
- 准备布局
/**
* 准备布局
*/
- (void)prepareLayout
{
[super prepareLayout];
// 初始化内容高度的变量
self.contentHeight = 0;
// 先移除之前的所有列数的高度数组
[self.colHeights removeAllObjects];
for (NSInteger i = 0 ; i < self.colCount; i++) {
// 初始化,赋值为一个顶部的类边距
[self.colHeights addObject:@(self.edgeInsets.top)];
}
// 清除之前所有布局属性的数组
[self.attriArrM removeAllObjects];
// collectionView第0组的所有元素
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger i = 0; i < count; i++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0] ;
UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attriArrM addObject:attr];
}
}
- 需要哪些布局
/**
* 返回全部的布局
*/
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
return self.attriArrM;
}
- 具体布局属性
/**
* 返回全部的布局属性
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
// collectionView的宽度
CGFloat collectionW = self.collectionView.frame.size.width;
// cell的尺寸
CGFloat w = (collectionW - self.edgeInsets.left - self.edgeInsets.right - (self.colCount - 1) * self.colMargin ) / self.colCount;
CGFloat h = [self.delegate WaterfallLayout:self heightForItemRowAtIndex:indexPath.item width:w];
// 最短的一列
NSInteger dustCol = 0;
// 取出第0列的高度
CGFloat minColHeight = [self.colHeights[0] doubleValue];
for (NSInteger i = 1; i < self.colCount; i++) {
// 第0列大于下一列
if (minColHeight > [self.colHeights[i] doubleValue]) {
minColHeight = [self.colHeights[i] doubleValue];
dustCol = i;
}
}
// cell的位置
CGFloat x = dustCol * (w + self.colCount) + self.edgeInsets.left;
CGFloat y = minColHeight;
if (y != self.edgeInsets.top) {
y += self.rowMargin;
}
// 设置cell的frame
attr.frame = CGRectMake(x, y, w, h);
// 更新当前列的高度
self.colHeights[dustCol] = @(CGRectGetMaxY(attr.frame));
// 当前列高度
CGFloat colHeight = [self.colHeights[dustCol] doubleValue];
// 当前列高度大于之前的内容高度
if (self.contentHeight < colHeight) {
// 赋值
self.contentHeight = colHeight;
}
return attr;
}
- 设置内容尺寸
/**
* 返回内容尺寸
*/
- (CGSize)collectionViewContentSize
{
return CGSizeMake(0, self.contentHeight + self.edgeInsets.bottom);
}
- 注册cell,实现代理方法
// 注册cell
[collectionView registerNib:[UINib nibWithNibName:NSStringFromClass([WZShopCell class]) bundle:nil] forCellWithReuseIdentifier:WZCellId];
self.collectionView = collectionView;
#pragma mark - <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
self.collectionView.footer.hidden = !self.shops.count;
return self.shops.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
WZShopCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:WZCellId forIndexPath:indexPath];
// 传递模型
cell.shop = self.shops[indexPath.item];
return cell;
}
- 实现自定义布局的代理方法
#pragma mark - <XMGWaterflowLayoutDelegate>
- (CGFloat)waterflowLayout:(XMGWaterflowLayout *)waterflowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth
{
XMGShop *shop = self.shops[index];
return itemWidth * shop.h / shop.w;
}
- (CGFloat)rowMarginInWaterflowLayout:(XMGWaterflowLayout *)waterflowLayout
{
return 20;
}
- (CGFloat)columnCountInWaterflowLayout:(XMGWaterflowLayout *)waterflowLayout
{
if (self.shops.count <= 50) return 2;
return 3;
}
- (UIEdgeInsets)edgeInsetsInWaterflowLayout:(XMGWaterflowLayout *)waterflowLayout
{
return UIEdgeInsetsMake(10, 20, 30, 100);
}