UICollectionView自定义layout如何实现? 比如瀑布流

实现UICollectionView自定义layout的方法:自定义一个类继承自UICollectionViewLayout类,重写下面方法:

//collectionview的内容尺寸
- (CGSize)collectionViewContentSize;
- (void)prepareLayout;


//返回所有元素的布局属性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;
//返回对应indexPath的cell的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
//返回对应于indexPath追加视图的布局属性,如果没有追加视图可不重载
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
//返回对应于indexPath装饰视图的布局属性,如果没有追加视图可不重载
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath;
//当边界发生改变时,是否应该刷新布局。如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;

自定义一个类WaterfallCollectionViewLayout继承自UICollectionViewLayout类    重写上面方法实现瀑布流布局


#import "WaterfallCollectionViewLayout.h"


//行距
static const CGFloat rowMargin = 10;
//列距
static const CGFloat columnMargin = 10;

static const UIEdgeInsets insets = {10, 10, 10, 10};

//列数
static const int columns = 3;

@interface WaterfallCollectionViewLayout()

//每一列的最大Y值
@property (nonatomic, strong) NSMutableArray *columnsMaxYarray;

//存放所有cell的布局属性
@property (nonatomic, strong) NSMutableArray *cellAttrisArray;

@end

@implementation WaterfallCollectionViewLayout

//懒加载
- (NSMutableArray *)columnsMaxYarray {
    if (!_columnsMaxYarray) {
        _columnsMaxYarray = [NSMutableArray array];
    }
    return _columnsMaxYarray;
}
- (NSMutableArray *)cellAttrisArray {
    if (!_cellAttrisArray) {
        _cellAttrisArray = [NSMutableArray array];
    }
    return _cellAttrisArray;
}


//collectionview的内容尺寸
- (CGSize)collectionViewContentSize {
    CGFloat maxY = [self.columnsMaxYarray[0] doubleValue];
    for (int i = 0; i < self.columnsMaxYarray.count; i++) {
        CGFloat columnY = [self.columnsMaxYarray[i] doubleValue];
        if (maxY < columnY) {
            maxY = columnY;
        }
    }
    return CGSizeMake(10, maxY + insets.bottom);
}


- (void)prepareLayout {
    [super prepareLayout];
    
    //重置每一列的最大Y值
    [self.columnsMaxYarray removeAllObjects];
    for (int i = 0; i < columns; i++) {
        [self.columnsMaxYarray addObject:@(insets.top)];
    }
    
    //计算所有cell的布局属性
    [self.cellAttrisArray removeAllObjects];
    NSInteger count = [self.collectionView numberOfItemsInSection:0];
    for (NSInteger i = 0; i < count; i++) {
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
        [self.cellAttrisArray addObject:attributes];
    }
}


//返回所有元素的布局属性
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    return self.cellAttrisArray;
}

//返回对应indexPath的cell的布局属性
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    //水平方向总间距
    CGFloat xMargin = insets.left + insets.right + (columns - 1)*columnMargin;
    //cell的宽度
    CGFloat w = (_totalWidth - xMargin)/columns;
    
    //cell?的高度
    CGFloat h = 50 + arc4random_uniform(150);
    
    //找最短的列号  和高度值
    CGFloat minY = [self.columnsMaxYarray[0] doubleValue];
    NSInteger minColumn = 0;
    for (int i = 0; i < self.columnsMaxYarray.count; i++) {
        CGFloat columnMaxY = [self.columnsMaxYarray[i] doubleValue];
        
        if (minY > columnMaxY) {
            minY = columnMaxY;
            minColumn = i;
        }
    }
   
   //cell的x值
    CGFloat x = insets.left + minColumn * (w + columnMargin);
    //cell的y值
    CGFloat y = minY + rowMargin;
    
    //cell的frame
    attribute.frame = CGRectMake(x, y, w, h);
    
    self.columnsMaxYarray[minColumn] = @(CGRectGetMaxY(attribute.frame));
    
    return attribute;
}



@end


调用

WaterfallCollectionViewLayout *layout = [[WaterfallCollectionViewLayout alloc]init];
    layout.totalWidth = 375;
    UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 375, 667) collectionViewLayout:layout];

效果


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值