您的位置:首页 > 产品设计 > UI/UE

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

2017-07-07 09:32 417 查看
实现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];


效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: