瀑布流的实现原理

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




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值