瀑布流的实现不同的人有不同的方法,个人认为最靠谱的莫过于用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