首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS_WaterfallFlowLayout瀑布流用重写UICollectionViewFlowLayout类实现

iOS_WaterfallFlowLayout瀑布流用重写UICollectionViewFlowLayout类实现

作者头像
mikimo
发布2022-07-20 13:32:37
发布2022-07-20 13:32:37
48900
代码可运行
举报
文章被收录于专栏:iOS开发~iOS开发~
运行总次数:0
代码可运行

最近调研瀑布流,在gitHub上下了个Demo发现它的所有视图都是用Main.storyboard拖的, 自己研究半天没研究明白;

然后就又找了一个Demo, 它的视图全是手打的, 但是实现的方法不太好,就将这俩Demo结合了一下:

用了gitHub的实现原理 和 另一个Demo的视图.

实现瀑布流最重要的一步就是重写UICollectionViewFlowLayout类, 下面就简单介绍一下实现原理

本方法实现的仅是高度不一样, 宽度是根据屏宽平均分的;

当创建UICollectionView的UICollectionViewFlowLayout属性时,给它传进去了两个属性: 列数, 和需要显示的Model数组 (这里是商品model(图片,价钱))

WaterfallFlowLayout.h

代码语言:javascript
代码运行次数:0
运行
复制
//  WaterfallFlowLayout.h
@interface WaterfallFlowLayout : UICollectionViewFlowLayout

// 总列数
@property (nonatomic, assign) NSInteger columnCount;

// 商品数据数组
@property (nonatomic, strong) NSArray *goodsArray;

@end

在.m文件里就根据这两个属性计算每个frame的大小, 用一个数组记录每列的高度, 每次计算frame时就将它放到最短列下面:

仅为计算item属性数组  和 itemSize, 然后在layoutAttributesForElementsInRect返回了该数组,就算是改变了每个item的frame了

代码语言:javascript
代码运行次数:0
运行
复制
<span style="font-family: Arial, Helvetica, sans-serif;">//  WaterfallFlowLayout.m</span>
代码语言:javascript
代码运行次数:0
运行
复制
#import "WaterfallFlowLayout.h"
#import "Good.h"

@interface WaterfallFlowLayout ()
// 所有item的属性的数组
@property (nonatomic, strong) NSArray *layoutAttributesArray;
@end

@implementation WaterfallFlowLayout

/**
 *  布局准备方法 当collectionView的布局发生变化时 会被调用
 *  通常是做布局的准备工作 itemSize.....
 *  UICollectionView 的 contentSize 是根据 itemSize 动态计算出来的
 */
- (void)prepareLayout {
    // 根据列数 计算item的宽度 宽度是一样的
    CGFloat contentWidth = self.collectionView.bounds.size.width - self.sectionInset.left - self.sectionInset.right; //减去分区的边框
    CGFloat marginX = self.minimumInteritemSpacing;  //最小左右间距
    CGFloat itemWidth = (contentWidth - marginX * (self.columnCount - 1)) / self.columnCount;
    
    // 计算布局属性
    [self computeAttributesWithItemWidth:itemWidth];
}

#pragma mark 根据itemWidth计算布局属性
- (void)computeAttributesWithItemWidth:(CGFloat)itemWidth {
    
    // 定义一个列高数组 记录每一列的总高度
    CGFloat columnHeight[self.columnCount];
    // 初始化
    for (int i = 0; i < self.columnCount; i++) {
        columnHeight[i] = self.sectionInset.top;
    }
    
    // 遍历 goodsList 数组计算相关的属性
    NSMutableArray *attributesArray = [NSMutableArray arrayWithCapacity:self.goodsArray.count];
    
    //因为item数是跟当前的商品数一样的 每次改变都动态计算一遍
    for (NSInteger i = 0; i < self.goodsArray.count; i++) {
        Good *good = self.goodsArray[i];
        // 建立布局属性
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        // 获得当前item的布局属性
        UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        // 找出最短列号
        NSInteger column = [self shortestColumn:columnHeight];
        // X值
        CGFloat itemX = (itemWidth + self.minimumInteritemSpacing) * column + self.sectionInset.left;
        // Y值 = 当前列的总高度
        CGFloat itemY = columnHeight[column];
        // 等比例缩放 计算item的高度
        CGFloat itemH = good.h * itemWidth / good.w;
        // 设置frame
        attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemH);
        [attributesArray addObject:attributes];
        
        //!!!!!!!!
        self.itemSize = CGSizeMake(itemWidth, itemH);

        // 累加当前列高
        columnHeight[column] += itemH + self.minimumLineSpacing;
        
    }
    // 给属性数组设置数值
    self.layoutAttributesArray = attributesArray.copy;
}

#pragma mark 找出columnHeight数组中最短列号 追加数据的时候追加在最短列中
- (NSInteger)shortestColumn:(CGFloat *)columnHeight {
    
    CGFloat min = CGFLOAT_MAX;
    NSInteger column = 0;
    // 循环列高数组
    for (int i = 0; i < self.columnCount; i++) {
        if (columnHeight[i] < min) {
            min = columnHeight[i];
            column = i;
        }
    }
    return column;
}

/**
 *  跟踪效果:当到达要显示的区域时 会计算所有显示item的属性
 *           一旦计算完成 所有的属性会被缓存 不会再次计算
 *  @return 返回布局属性(UICollectionViewLayoutAttributes)数组
 */
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    // 直接返回计算好的布局属性数组
    return self.layoutAttributesArray;
}

一下是Demo下载地址:

http://download.csdn.net/detail/margaret_mo/9417425

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档