建立瀑布流有三種方式:git
//每一次從新佈局前,都會準備佈局(蘋果官方推薦使用該方法進行一些初始化)github
-(void)prepareLayout數組
//重寫layoutAttributesForItemAtIndexPath,返回每個item的佈局屬性(流式佈局內部已經幫助完成)佈局
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPathatom
//是否要從新刷新佈局(只要顯示的item邊界發生改變就從新佈局)spa
//只要每一次從新佈局內部就會調用下面的layoutAttributesForElementsInRect:獲取全部cell(item)的屬性代理
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBoundscode
//返回須要從新佈局的全部item屬性orm
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rectblog
🐷:下面的瀑布流佈局能夠直接拿走使用
下面使用第三種方式建立的瀑布流代碼以下:
WaterFlowLayout.h
#import <UIKit/UIKit.h> /* 爲了體現封裝性的特色,咱們能夠把一些數據設置爲公共的,既能夠提升擴展性和通用性, 也便於外界按照本身的需求作必要的調整。 */ @protocol WaterFlowLayoutDelegate; //設置代理傳遞數據,下降了與其餘類的耦合性,通用性更強 @class WaterFlowLayout; @interface WaterFlowLayout : UICollectionViewLayout @property (assign,nonatomic)CGFloat columnMargin;//每一列item之間的間距 @property (assign,nonatomic)CGFloat rowMargin; //每一行item之間的間距 @property (assign,nonatomic)UIEdgeInsets sectionInset;//設置於collectionView邊緣的間距 @property (assign,nonatomic)NSInteger columnCount;//設置每一行排列的個數 @property (weak,nonatomic)id<WaterFlowLayoutDelegate> delegate; //設置代理 @end @protocol WaterFlowLayoutDelegate -(CGFloat)waterFlowLayout:(WaterFlowLayout *) WaterFlowLayout heightForWidth:(CGFloat)width andIndexPath:(NSIndexPath *)indexPath; @end
WaterFloeLayout.m
#import "WaterFlowLayout.h" //每一列item之間的間距 //static const CGFloat columnMargin = 10; //每一行item之間的間距 //static const CGFloat rowMargin = 10; @interface WaterFlowLayout() /** 這個字典用來存儲每一列item的高度 */ @property (strong,nonatomic)NSMutableDictionary *maxYDic; /** 存放每個item的佈局屬性 */ @property (strong,nonatomic)NSMutableArray *attrsArray; @end @implementation WaterFlowLayout /** 懶加載 */ -(NSMutableDictionary *)maxYDic { if (!_maxYDic) { _maxYDic = [NSMutableDictionary dictionary]; } return _maxYDic; } /** 懶加載 */ -(NSMutableArray *)attrsArray { if (!_attrsArray) { _attrsArray = [NSMutableArray array]; } return _attrsArray; } //初始化 -(instancetype)init { if (self = [super init]){ self.columnMargin = 10; self.rowMargin = 10; self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10); self.columnCount = 3; } return self; } //每一次佈局前的準備工做 -(void)prepareLayout { [super prepareLayout]; //清空最大的y值 for (int i =0; i < self.columnCount; i++) { NSString *column = [NSString stringWithFormat:@"%d",i]; self.maxYDic[column] = @(self.sectionInset.top); } //計算全部item的屬性 [self.attrsArray removeAllObjects]; NSInteger count = [self.collectionView numberOfItemsInSection:0]; for (int i=0; i<count; i++) { UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; [self.attrsArray addObject:attrs]; } } //設置collectionView滾動區域 -(CGSize)collectionViewContentSize { //假設最長的那一列爲第0列 __block NSString *maxColumn = @"0"; //遍歷字典,找出最長的那一列 [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] > [self.maxYDic[maxColumn] floatValue]) { maxColumn = column; } }]; return CGSizeMake(0, [self.maxYDic[maxColumn]floatValue]+self.sectionInset.bottom); } //容許每一次從新佈局 -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds { return YES; } //佈局每個屬性 -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { //假設最短的那一列爲第0列 __block NSString *minColumn = @"0"; //遍歷字典,找出最短的那一列 [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSString *column, NSNumber *maxY, BOOL *stop) { if ([maxY floatValue] < [self.maxYDic[minColumn] floatValue]) { minColumn = column; } }]; //計算每個item的寬度和高度 CGFloat width = (self.collectionView.frame.size.width - self.columnMargin*(self.columnCount - 1) - self.sectionInset.left - self.sectionInset.right) / self.columnCount; CGFloat height = [self.delegate waterFlowLayout:self heightForWidth:width andIndexPath:indexPath] ; //計算每個item的位置 CGFloat x = self.sectionInset.left + (width + self.columnMargin) * [minColumn floatValue]; CGFloat y = [self.maxYDic[minColumn] floatValue] + self.rowMargin; //更新這一列的y值 self.maxYDic[minColumn] = @(y + height); //建立佈局屬性 UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; //設置item的frame attrs.frame = CGRectMake(x, y, width, height); return attrs; } //佈局全部item的屬性,包括header、footer -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { return self.attrsArray; } @end
瀑布流演示結果以下:
github: https://github.com/xiayuanquan/XYQCollectionLayout.git