瀑布流的實現不同的人有不同的方法,個人認爲最靠譜的莫過於用UICollectionView來實現,只要明白其中的思想實現起來先就非常簡單了,其實博主也是在網上看別人寫的demo,下載下來研究弄明白的,給大家展示一下效果圖。
第一步、自定義UICollectionViewLayout,在.h文件中定義協議,協議方法有下面四個。
@class CustomCollectionViewLayout;
@protocol CustomCollectionViewLayoutDelegate <NSObject>
@required
/**
* @brief 每個cell之間的間距
*/
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout marginOfCellWithCollectionView:(UICollectionView *)collectionView;
/**
* @brief cell的最小高度
*/
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout minHeightOfCellWithCollectionView:(UICollectionView *)collectionView;
/**
* @brief cell的最大高度
*/
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout maxrOfCellWithCollectionView:(UICollectionView *)collectionView;
/**
* @brief 行數
*/
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout numberOfColumnWithCollectionView:(UICollectionView *)collectionView;
@end
第二步、在.m文件中定義屬性,實現協議方法
@interface CustomCollectionViewLayout ()
@property (nonatomic,assign) NSInteger numberOfSections;//section的數量
@property (nonatomic,assign) NSInteger numberOfCellInSections;//section中cell的數量
@property (nonatomic,assign) NSInteger columnCount;//行數
@property (nonatomic,assign) NSInteger margin;//cell之間的間距
@property (nonatomic,assign) NSInteger cellMinHeight;//cell的最小高度
@property (nonatomic,assign) NSInteger cellMaxHeight;//cell的最大高度
@property (nonatomic,assign) NSInteger cellWidth;//cell的寬度
@property (nonatomic,strong) NSMutableArray * cellHeightArray;//存儲每個cell的隨機高度
@property (nonatomic,strong) NSMutableArray * cellXArray;//存儲每列cell的X座標
@property (nonatomic,strong) NSMutableArray * cellYArray;//存儲每列cell的最新cell的Y座標
@end
- (void)initCustonCollectionViewLayoutDate{
_numberOfSections = [self.collectionView numberOfSections];
_numberOfCellInSections = [self.collectionView numberOfItemsInSection:0];
_margin = [_delegate CustomCollectionViewLayout:self marginOfCellWithCollectionView:self.collectionView];
_columnCount = [_delegate CustomCollectionViewLayout:self numberOfColumnWithCollectionView:self.collectionView];
_cellMinHeight = [_delegate CustomCollectionViewLayout:self minHeightOfCellWithCollectionView:self.collectionView];
_cellMaxHeight = [_delegate CustomCollectionViewLayout:self maxrOfCellWithCollectionView:self.collectionView];
}
第三步、重寫prepareLayout方法,在這個方法中我們要初始化一些數據
/**
* @brief 預加載layout,只會被執行一次
*/
- (void)prepareLayout{
[super prepareLayout];
[self initCustonCollectionViewLayoutDate];
[self initCustonCollectionViewLayoutCellWidth];
[self initCustonCollectionViewLayoutCellHeight];
}
第四步、實現核心方法,就是爲每一個cell綁定一個Layout屬性
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
[self initCellYArray];
NSMutableArray * array = [NSMutableArray array];
for (int i = 0; i < _numberOfCellInSections; i ++) {
NSIndexPath * indexPath = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes * attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
[array addObject:attributes];
}
return array;
}
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes * attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
CGRect frame = CGRectZero;
CGFloat cellHeight = [[_cellHeightArray objectAtIndex:indexPath.row] floatValue];
NSInteger minYIndex = [self selectMinIndexWithArray:_cellYArray];
CGFloat X = [[_cellXArray objectAtIndex:minYIndex] floatValue];
CGFloat Y = [[_cellYArray objectAtIndex:minYIndex] floatValue];
frame = CGRectMake(X, Y, _cellWidth, cellHeight);
_cellYArray[minYIndex] = @(Y + cellHeight + _margin);//更新相應的Y座標
attributes.frame = frame;//計算每個cell的位置
return attributes;
}
第五步、集成。如果是用StoryBoard拖得可能稍微簡單一點,當然代碼書寫也不難。拿到代理,實現代理方法就行。
#pragma mark --- CustomCollectionViewLayoutDelegate
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout marginOfCellWithCollectionView:(UICollectionView *)collectionView{
return 2;
}
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout maxrOfCellWithCollectionView:(UICollectionView *)collectionView{
return 150;
}
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout minHeightOfCellWithCollectionView:(UICollectionView *)collectionView{
return 100;
}
-(NSInteger)CustomCollectionViewLayout:(CustomCollectionViewLayout *)collectionViewLayout numberOfColumnWithCollectionView:(UICollectionView *)collectionView{
return 2;
}
注意點:如果是用StoryBoard拖一定注意cell的重用、Layout的指定(因爲我們自定義了UICollectionViewLayout);代碼是實現的話就需要細心一點兒就ok。
代碼傳送門:https://github.com/fuzongjian/WaterFall.git