瀑布流
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;
}
代码里用到了部分自定义宏,自行更改即可