UICollectionView簡單瀑布流實現

1.如何實現瀑布流?

繼承基類UICollectionViewLayout,並實現方法,並在UICollectionView中使用這個佈局。

2.如何實現UICollectionViewLayout子類的方法

實現下面四個方法

//1.告訴當前layout對象,更新當前佈局
- (void)prepareLayout;

//2.返回指定indexPath下的 UICollectionViewLayoutAttributes
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;

//3.返回collectionView的ContentSize
//由於瀑布流每一列的高度不一定,所以需要判讀出最高的列作爲height
-(CGSize)collectionViewContentSize;
  
//4.返回UICollectionViewLayoutAttributes屬性數組
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect;

UICollectionViewLayoutAttributes是用於存儲UICollectionViewcell佈局屬性的類。

3.其它變量

//用於存儲UICollectionViewLayoutAttributes的數組
NSMutableArray * attributeArray; 

//列數
NSInteger _collectViewRowCount;

//記錄每一列的Y點座標,最後獲取其中的最大值,相當於collectionView的contentSize.height
NSMutableArray * _originYAry;    

 

4.完整UICollectionViewLayout子類代碼

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface CustomLayout : UICollectionViewLayout

@end

NS_ASSUME_NONNULL_END

#import "CustomLayout.h"


@implementation CustomLayout{
    NSMutableArray * attributeArray; // frame 數組
    NSInteger _collectViewRowCount;  // 列數
    NSMutableArray * _originYAry;    //記錄每一列的Y點座標
}


- (instancetype)init
{
    self = [super init];
    if (self) {
        attributeArray = [NSMutableArray array];
        _originYAry = [NSMutableArray array];
        _collectViewRowCount = 3;
    }
    return self;
}

//1.告訴當前layout對象,更新當前佈局
- (void)prepareLayout{
    
    [attributeArray removeAllObjects];
    [_originYAry removeAllObjects];
    
    //初始化y座標
    for (int i =0; i <_collectViewRowCount; i++) {
        [_originYAry addObject:@(0)];
    }
    
    //返回
    NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];
        
    for (int i = 0; i < cellCount; i ++ ) {
            
        NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            
        //UICollectionViewLayoutAttributes 用於存儲layout屬性的對象
        UICollectionViewLayoutAttributes *attrib = [self layoutAttributesForItemAtIndexPath:indexPath];
            
        [attributeArray addObject:attrib];
    }
}

//2.返回指定indexPath下的 UICollectionViewLayoutAttributes
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    //根據indexPath創建一個UICollectionViewLayoutAttributes
    UICollectionViewLayoutAttributes *layoutAttr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    
    //設置每個frame
    CGFloat width = [UIScreen mainScreen].bounds.size.width /_collectViewRowCount;
    CGFloat height = 50 + arc4random_uniform(20);
    CGFloat x = width * ( indexPath.row % _collectViewRowCount);
    
    CGFloat y = [_originYAry[indexPath.row % _collectViewRowCount] floatValue];
    _originYAry[indexPath.row % _collectViewRowCount] = @(height + y +10);
    layoutAttr.frame =CGRectMake(x, y, width, height);
    
    return layoutAttr;
}

//3.返回collectionView的ContentSize
//由於瀑布流每一列的高度不一定,所以需要判讀出最高的列作爲height
-(CGSize)collectionViewContentSize{
    
    //kvc 獲取最大值
    CGFloat maxY =[[_originYAry valueForKeyPath:@"@max.floatValue"] floatValue];
    return CGSizeMake([UIScreen mainScreen].bounds.size.width, maxY);
}

//4.Returns the layout attributes for all of the cells and views in the specified rectangle.
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    return attributeArray;
}

@end

在UICollectionView中設置其layout

[self.collectionView setCollectionViewLayout:[CustomLayout new]];

注意:默認section的數量是1。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章