利用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