瀑布流的實現原理

瀑布流的實現不同的人有不同的方法,個人認爲最靠譜的莫過於用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




發佈了64 篇原創文章 · 獲贊 10 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章