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

来源:互联网 发布:电力行业数据 编辑:程序博客网 时间:2024/06/05 21:00

实现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];

效果


原创粉丝点击