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。