利用UICollectionView实现瀑布流

利用UICollectionView实现瀑布流通过自定义布局来实现。

- 自定义类继承UICollectionViewLayout;

必须重写的方法有:  

//决定每个item的位置;

- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

//布局layout

- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

//滚动的范围,类似于scrollview的contentSize

- (CGSize)collectionViewContentSize;

@protocol WJLWaterFallLayoutDelegate;

@interface WJLWaterFallLayout : UICollectionViewLayout

@property(nonatomic,assign)int colCount;//列数
@property(nonatomic,assign)CGFloat colSpace;//列间距
@property(nonatomic,assign)CGFloat lineSpace;//行间距
@property(nonatomic,assign)UIEdgeInsets sectionInsets;
@property(nonatomic,weak) id <WJLWaterFallLayoutDelegate> delegate;

@end

@protocol WJLWaterFallLayoutDelegate <NSObject>

@required
//通过代理得到每个item 的一个高度
- (CGFloat)collectionViewLayout:(WJLWaterFallLayout*)layout heightAtIndexPath:(NSIndexPath*)indexPath;
#import "WJLWaterFallLayout.h"

static const int colCount = 3;//默认列数
static const CGFloat space = 10;//默认间距

@interface WJLWaterFallLayout()

@property(nonatomic,strong)NSMutableDictionary *maxDic;//储存列的长度

@end

@implementation WJLWaterFallLayout

- (instancetype)init{
    if (self = [super init]) {
        self.colCount = colCount;
        self.lineSpace = space;
        self.colSpace = space;
        self.sectionInsets = UIEdgeInsetsMake(space, space, space, space);
        self.maxDic = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)prepareLayout{
    [super prepareLayout];
}
/**
 * 决定collectionview能滑动的范围
 */
- (CGSize)collectionViewContentSize{
    __block NSString *maxCol = @"0";
    //找到最长的列
    [self.maxDic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj floatValue] > [self.maxDic[maxCol] floatValue]) {
            maxCol = key;
        }
    }];
    CGFloat maxY = [self.maxDic[maxCol] floatValue]+self.lineSpace;
    return CGSizeMake(0, maxY) ;
}
/**
 *  布局layout
 */
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    for (int i = 0; i < self.colCount; i ++) {
        NSString *key = [NSString stringWithFormat:@"%d",i];
        self.maxDic[key] = @0;
    }
    
    NSMutableArray *arr = [NSMutableArray array];
    int count = (int)[self.collectionView numberOfItemsInSection:0];
    
    for (int i = 0 ; i < count ; i ++) {
        UICollectionViewLayoutAttributes *att = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
        [arr addObject:att];
    }
    
    return arr;
}
/**
    决定了每个item的位置,大小
 */
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    __block NSString *minCol = @"0";
    [self.maxDic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        if ([obj floatValue] < [self.maxDic[minCol] floatValue] ) {
            minCol = key;
        }
    }];
    int col = [minCol intValue];
    CGFloat nowY = [self.maxDic[minCol] floatValue];//当前列的y值
    
    CGFloat itemW = (self.collectionView.frame.size.width - self.sectionInsets.left - self.sectionInsets.right - self.colSpace*(self.colCount - 1))/(self.colCount);
    CGFloat itemH = 0 ;
    if ([self.delegate respondsToSelector:@selector(collectionViewLayout:heightAtIndexPath:)]) {
        itemH = [self.delegate collectionViewLayout:self heightAtIndexPath:indexPath];
    }
    CGFloat x = self.sectionInsets.left + (itemW + self.colSpace) * col;
    CGFloat space = 0 ;
    
    if (indexPath.row < self.colCount) {//第一行的时候y值 
        space = self.sectionInsets.top;
    }else {
        space = self.lineSpace;
    }
    CGFloat y = nowY +  space;
    
    self.maxDic[minCol] = @(y + itemH);//更新此列的y值
    
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    attributes.frame = CGRectMake(x, y, itemW, itemH);
    
    return attributes;
}
@end
原文地址:https://www.cnblogs.com/cnman/p/5193945.html