UIKIt框架-自定义视图-瀑布流

瀑布流
效果图

这里写图片描述

1.新建一个继承UICollectionViewLayout的子类
2.定义属性
static const NSInteger count = 3;// 默认列数
static const CGFloat rowmagin = 10;// 行间距
static const CGFloat columnmagin = 10;// 列间距
static const UIEdgeInsets edge = {10,10,10,10};// 边缘间距
/** 存放每个item的属性数组 */
@property (nonatomic,strong) NSMutableArray *array;
/** 存放最短高度的数组 */
@property (nonatomic,strong) NSMutableArray *minheight;
/** 内容的高度 */
@property (nonatomic,assign) CGFloat contentH;
3.实现prepareLayout方法(准备布局)
// 准备布局
- (void)prepareLayout {
    [super prepareLayout];

    // 清除之前计算的所有高度
    [self.minheight removeAllObjects];
    //给数组初始化值,防止数组越界
    for (NSInteger i = 0; i < count; i++) {
        [self.minheight addObject:@(edge.top)];
    }

    // 清除之前所有的布局属性
    [self.array removeAllObjects];

    // 1.创建每个item的属性
    // 获取第0section的item个数
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    // for循环给每个item创建属性
    for (int i=0; i<count; i++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        UICollectionViewLayoutAttributes *attr = [self layoutAttributesForItemAtIndexPath:indexPath];
        // 将属性加入属性数组中
        [self.array addObject:attr];
    }   
}
4.实现layoutAttributesForItemAtIndexPath方法创建item属性
// 设置单个item的属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    // 1. 常见item属性
    UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    CGFloat collectViewW = self.collectionView.frame.size.width;
    // 计算宽度
    CGFloat w = (collectViewW - edge.left - edge.right - columnmagin * (count - 1)) / count;
    // 高度为50~250之间随机数
    CGFloat h = arc4random()%200 + 50;

    // 假如最短的那列为第0列
    NSInteger minColumn = 0;
    // 这里要注意数组越界(一开始数组里面先初始化值)
    CGFloat minColumnHeight = [self.minheight[0] doubleValue]; // 最短那列的高度

    // 通过比较获取实际最短的那列高度
    for (NSInteger i=1; i<count; i++) {
        // 获取第i列的高度
        CGFloat columnHeight = [self.minheight[i] doubleValue];

        // 比较并找出最短列
        if (minColumnHeight > columnHeight) {
            minColumnHeight = columnHeight;
            minColumn = i;
        }
    }

    // 获取x、y
    CGFloat x = edge.left + minColumn * (w + columnmagin);
    CGFloat y = minColumnHeight;
    // 判断是否是在第一行,如果不是,就增加行间距
    if (y != edge.top) {
        y += rowmagin;
    }

    // 设置frame
    attr.frame = CGRectMake(x, y, w, h);

    // 更新最短那列
    self.minheight[minColumn] = @(CGRectGetMaxY(attr.frame));

    // 记入内容的高度
    CGFloat contentH = [self.minheight[minColumn] doubleValue];
    if (self.contentH < contentH) {
        self.contentH = contentH;
    }

    return attr;
}
5.实现layoutAttributesForElementsInRect方法,返回所有item的属性(也就是刚刚保存属性的那个数组)
// 返回每个item的属性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
    return self.array;
}
6.实现collectionViewContentSize方法设置内容高度
// 设置内容的尺寸
- (CGSize)collectionViewContentSize {
    return CGSizeMake(0 , self.contentH + edge.bottom);
}
7.想要动态改变item的高度,创建代理协议
@class WaterLayou;
@protocol WaterDelegate <NSObject>
// 动态获取item的高度
- (CGFloat)waterFlowLayout:(WaterLayou *)waterFlowLayout heightForItemAtIndex:(NSUInteger)index itemWidth:(CGFloat)itemWidth;
@end
@interface WaterLayou : UICollectionViewLayout
/** 代理 */
@property (nonatomic,weak) id <WaterDelegate>waterdelegate;
@end

// 设置item的属性高度
    CGFloat h = [self.delegate waterFlowLayout:self heightForItemAtIndex:indexPath.item itemWidth:w];
点击获取对应Demo示例

仅供参考,错误勿怪!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值