iOS 瀑布流的理解和封装

瀑布流的实现方法

  • 第一种方法:在底部放一个scrollView,根据内容的大小定制view的大小,在scrollView上面进行排列,因为展示的内容太多,所以最好让view进行复用,这样的方法还是挺复杂的。
  • 第二种方法:在iOS6之后有了流布局之后,由系统帮你实现cell复用,工作就简单了很多。
今天主要说的就是第二种方法,实现瀑布流的思路及做简单的封装
  • 因为瀑布流也是一种布局,所以我们不能去继承流布局本身的流水布局,因为那种布局每个格子的大小都是固定的。所以我们要继承 UICollectionViewLayout
  • 我们需要实现的方法
    - (void)prepareLayout 每一次刷新对设置进行初始化,去清除之前计算的数据
    - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 返回每一个cell的属性
    - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 设置每一个cell对应的属性
    - (CGSize)collectionViewContentSize 返回内容的高度,内容的高度根据最后一行最长的一列计算
  • 我们需要针对数据源的高去写cell的高,因为瀑布流是长短不一的,所以我们需要计算出每一行最短的那一列
    下面贴出动态计算cell高度的代码吧
/** 返回indexPath位置cell对应的布局属性*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //先创建布局属性
    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

    //cell宽度 = (collectionView的宽度 - 左边距 - 右边距 - (列数 - 1)* 列间距)/ 3
    CGFloat width = (self.collectionView.frame.size.width - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
    //cell高度 = 传进来的高度
    CGFloat height = [self.delegate waterflowLayout:self heightForItemAtIndex:indexPath.item itemWidth:width];

    //如果是第一行
    //y = 上边距

    /**
     * 如果不是第一行,需要找出最短的一列
     * 初始化的时候,用一个数组存储第一行的每个cell的maxY值
     * 定义一个最短高度的变量,遍历cellmaxY值数组,让变量等于最短的那一个,得到最短的列
     */
    //最短的行号,默认第一列
    NSInteger minColumnCount = 0;
    //最短的y值,默认第一列
    CGFloat minColunmnMaxY = [self.columnHeights[0] floatValue];

    for (NSInteger i = 1; i < self.columnCount; ++i)
    {
        //取出第i列高度
        CGFloat columnHeight = [self.columnHeights[i] floatValue];

        if (minColunmnMaxY > columnHeight)
        {
            minColunmnMaxY = columnHeight;
            minColumnCount = i;
        }
    }



    //x = 左边距 + 最短列位置 * (宽度 + 列间距)
    CGFloat x = self.edgeInsets.left + minColumnCount * (width + self.columnMargin);
    //有了最短的行,y = 最短列maxY值 + 列间距
    CGFloat y = minColunmnMaxY;
    if (y != self.edgeInsets.top)
    {
        y += self.rowMargin;
    }

    //设置frame
    attributes.frame = CGRectMake(x, y, width, height);

    //更新高度
    self.columnHeights[minColumnCount] = @(CGRectGetMaxY(attributes.frame));

    // 记录内容的高度
    CGFloat columnHeight = [self.columnHeights[minColumnCount] floatValue];
    if (self.contentHeight < columnHeight)
    {
        self.contentHeight = columnHeight;
    }


    return attributes;
}
  • 这里已经计算出了最短的列和最长的列,所以每一个cell该怎么放,以及整个UICollectionView的内容大小也已经计算出来
今天就到这里吧,感觉写的也不太满意,哪里有问题可以指出来。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值