纵向等宽多组瀑布流

瀑布流

TTWaterfallFlowLayout.h
#import 

NS_ASSUME_NONNULL_BEGIN

@class TTWaterfallFlowLayout;

@protocol TTWaterfallFlowLayoutDelegate 
@required
- (CGSize)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
- (CGSize)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout sizeForHeaderAtIndexPath:(NSIndexPath *)indexPath;
- (CGSize)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout sizeForFooterAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout numForColumnsInSection:(NSInteger )section;
@end

@interface TTWaterfallFlowLayout : UICollectionViewFlowLayout

/// 左边距 默认10
@property (nonatomic, assign) CGFloat leftMargin;

/// 右边距  默认10
@property (nonatomic, assign) CGFloat rightMargin;

/// 行间距
@property (nonatomic, assign) CGFloat rowMargin;

/// 列边距
@property (nonatomic, assign) CGFloat columnsMargin;

/// 列数  默认2列 == 
@property (nonatomic, assign) NSInteger columns;

@property (nonatomic, weak) iddelegate;

@end

NS_ASSUME_NONNULL_END
TTWaterfallFlowLayout.m
#import "TTWaterfallFlowLayout.h"

@interface TTWaterfallFlowLayout ()

@property (nonatomic, strong) NSMutableArray *attributeArray;
@property (nonatomic, strong) NSMutableArray *lowestYArr;
@end

@implementation TTWaterfallFlowLayout

- (instancetype)init {
    self = [super init];
    if (self) {
        self.lowestYArr = [NSMutableArray arrayWithArray:@[@(0),@(0)]];
        
        self.leftMargin =10;
        self.rightMargin =10;
        self.columnsMargin =10;
        self.rowMargin =10;
        self.columns = 2;
    }
    return self;
}

- (void)prepareLayout {
    //清除历史布局
    self.attributeArray = [NSMutableArray array];
    [self.lowestYArr removeAllObjects];
    for (int i=0; i *)layoutAttributesForElementsInRect:(CGRect)rect{
    return self.attributeArray;
}
//返回cell的布局
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    //获取列数,根据列数改变
    if ([self.delegate respondsToSelector:@selector(waterfallFlowLayout:numForColumnsInSection:)]) {
        self.columns = [self.delegate waterfallFlowLayout:self numForColumnsInSection:indexPath.section];
    }
    
    UICollectionViewLayoutAttributes *attri = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    //计算
    attri.frame = [self itemFrameOfVerticalWaterfallFlow:indexPath];
    return attri;
}
//返回头尾视图的布局
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes *attri;
    
    if ([elementKind isEqualToString:UICollectionElementKindSectionHeader]) { //头视图
        attri = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:indexPath];
        CGFloat h = 0;
        if ([self.delegate respondsToSelector:@selector(waterfallFlowLayout:sizeForHeaderAtIndexPath:)]) {
            h = [self.delegate waterfallFlowLayout:self sizeForHeaderAtIndexPath:indexPath].height;
        }
        attri.frame = CGRectMake(0, [self getHighestYInArr:self.lowestYArr], SCREEN_WIDTH, h);
    }else { //脚视图
        attri = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionFooter withIndexPath:indexPath];
        CGFloat h = 0;
        if ([self.delegate respondsToSelector:@selector(waterfallFlowLayout:sizeForFooterAtIndexPath:)]) {
            h = [self.delegate waterfallFlowLayout:self sizeForHeaderAtIndexPath:indexPath].height;
        }
        attri.frame = CGRectMake(0, [self getHighestYInArr:self.lowestYArr], SCREEN_WIDTH, h);
    }
    // 更新Y数据
    CGFloat highest = [self getHighestYInArr:self.lowestYArr] +attri.bounds.size.height;
    NSInteger count = self.lowestYArr.count;
    [self.lowestYArr removeAllObjects];
    for (int i=0; i*)arr {
    
    NSInteger index = 0;
    CGFloat min = [arr[0] floatValue];
    
    for (int i=0; i*)arr {
    
    CGFloat max = [arr[0] floatValue];
    
    for (int i=0; i max) {
            max = [arr[i] floatValue];
        }
    }
    
    return max;
}
#pragma mark -- SET
- (void)setColumns:(NSInteger)columns {
    if (_columns != columns) { //列数更改后需要重新设置y数据
        //需重新设置位置
        CGFloat highest = [self getHighestYInArr:self.lowestYArr];
        [self.lowestYArr removeAllObjects];
        for (int i=0; i

使用

TTWaterfallFlowLayout *flowLayout = [TTWaterfallFlowLayout new];
flowLayout.delegate = self;

同系统创建flowLayout,设置代理

实现代理方法

#pragma mark -- TTWaterfallFlowLayoutDelegate
- (CGSize)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout sizeForHeaderAtIndexPath:(NSIndexPath *)indexPath {
    // 代码里写死为屏幕宽度,这里宽度无用到
    return CGSizeMake(0,150);
}
- (CGSize)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    // 因为只实现了等宽不等高的一种情况。所以宽度是自动根据间距自动算出来的。这里宽度无效,可自行扩展
    if (indexPath.section == 0) {
        return CGSizeMake(0, 60);
    }else if (indexPath.section == 1) {
        return CGSizeMake(0, 160);
    }
    return CGSizeMake(0, 200+arc4random()%200);
}
- (NSInteger)waterfallFlowLayout:(TTWaterfallFlowLayout *)flowLayout numForColumnsInSection:(NSInteger)section {
    if (section == 0) {
        return 5;
    }else if (section == 1) {
        return 3;
    }
    return 2;
}

代码里用到了部分自定义宏,自行更改即可

你可能感兴趣的:(纵向等宽多组瀑布流)