博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS--collectionView简单瀑布流的实现
阅读量:6388 次
发布时间:2019-06-23

本文共 6308 字,大约阅读时间需要 21 分钟。

在看此篇文章之前,希望你已经有了一些对collectionView的理解。 ####一. 自定义layout 就像实现tableview的功能去自定义cell是差不多的,瀑布流的思路就是哪一列最短,就把下一个item放在哪一列。这样我们需要的属性就有,列间距,行间距,边距,还有保存item的attributes的数组。

//总列数@property (nonatomic, assign) NSInteger columnCount;//列间距@property (nonatomic, assign) NSInteger columnSpacing;//行间距@property (nonatomic, assign) NSInteger rowSpacing;//section到collectionView的边距@property (nonatomic, assign) UIEdgeInsets sectionInset;//保存每一列最大y值的数组@property (nonatomic, strong) NSMutableDictionary *maxYDic;//保存每一个item的attributes的数组@property (nonatomic, strong) NSMutableArray *attributesArray;//代理,用来计算item的高度@property (nonatomic, weak) id
delegate;复制代码

接下来需要重写四个layout的系统方法 ######(1)- (void)prepareLayout 方法

//布局前的准备工作- (void)prepareLayout {    [super prepareLayout];    //初始化字典,有几列就有几个键值对,key为列,value为列的最大y值,初始值为上内边距    for (int i = 0; i < self.columnCount; i++) {        self.maxYDic[@(i)] = @(self.sectionInset.top);    }        //根据collectionView获取总共有多少个item    NSInteger itemCount = [self.collectionView numberOfItemsInSection:0];    [self.attributesArray removeAllObjects];    //为每一个item创建一个attributes并存入数组    for (int i = 0; i < itemCount; i++) {        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];        [self.attributesArray addObject:attributes];    }}复制代码

######(2)- (CGSize)collectionViewContentSize方法

//计算collectionView的contentSize- (CGSize)collectionViewContentSize {    __block NSNumber *maxIndex = @0;    //遍历字典,找出最长的那一列    [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {        if ([self.maxYDic[maxIndex] floatValue] < obj.floatValue) {            maxIndex = key;        }    }];        //collectionView的contentSize.height就等于最长列的最大y值+下内边距    return CGSizeMake(0, [self.maxYDic[maxIndex] floatValue] + self.sectionInset.bottom);}复制代码

######(3)- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath 方法 该方法则用来设置每个item的attributes,在这里,我们只需要简单的设置每个item的attributes.frame即可,首先我们必须得知collectionView的尺寸,然后我们根据collectionView的宽度,以及列数、各个间距来计算每个item的宽度

######item的宽度 = (collectionView的宽度 - 内边距及列边距) / 列数

CGFloat collectionViewWidth = self.collectionView.frame.size.width;//self.sectionInset.left:左边距    self.sectionInset.right:右边距//(self.columnCount - 1) * columnSpacing:一行中所有的列边距CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.columnCount - 1) * self.columnSpacing) / self.columnCount;复制代码

######item的y值就等于最短列的最大y值再加上行间距,x值就等于左边距 + (item宽度 + 列间距) * minColumn

//找出最短的那一列__block NSNumber *minIndex = @0;[self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {    if ([self.maxYDic[minIndex] floatValue] > obj.floatValue) {        minIndex = key;    }}];//根据最短列的列数计算item的x值CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.integerValue;//item的y值 = 最短列的最大y值 + 行间距CGFloat itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;复制代码

接下来便是item的高度,我们应该根据图片的原始尺寸以及计算出来的宽度,等比例缩放来计算高度,但是在layout类中,我们是拿不到图片的,因此我们可以定义一个block属性,或者代理,让外界来计算并返回给我们,我们需要将item的宽度以及indexPath传递给外界

@required//计算item高度的代理方法,将item的高度与indexPath传递给外界- (CGFloat)waterfallLayout:(XRWaterfallLayout *)waterfallLayout itemHeightForWidth:(CGFloat)itemWidth atIndexPath:(NSIndexPath *)indexPath;@end复制代码

见详细代码?:

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {    //根据indexPath获取item的attributes    UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];        //获取collectionView的宽度    CGFloat collectionViewWidth = self.collectionView.frame.size.width;        //item的宽度 = (collectionView的宽度 - 内边距与列间距) / 列数    CGFloat itemWidth = (collectionViewWidth - self.sectionInset.left - self.sectionInset.right - (self.columnCount - 1) * self.columnSpacing) / self.columnCount;        CGFloat itemHeight = 0;    //获取item的高度,由外界计算得到        if ([self.delegate respondsToSelector:@selector(waterfallLayout:itemHeightForWidth:atIndexPath:)])            itemHeight = [self.delegate waterfallLayout:self itemHeightForWidth:itemWidth atIndexPath:indexPath];        //找出最短的那一列    __block NSNumber *minIndex = @0;    [self.maxYDic enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, NSNumber *obj, BOOL *stop) {        if ([self.maxYDic[minIndex] floatValue] > obj.floatValue) {            minIndex = key;        }    }];        //根据最短列的列数计算item的x值    CGFloat itemX = self.sectionInset.left + (self.columnSpacing + itemWidth) * minIndex.integerValue;        //item的y值 = 最短列的最大y值 + 行间距    CGFloat itemY = [self.maxYDic[minIndex] floatValue] + self.rowSpacing;        //设置attributes的frame    attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);        //更新字典中的最大y值    self.maxYDic[minIndex] = @(CGRectGetMaxY(attributes.frame));        return attributes;}复制代码

######(4)- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect 方法 直接返回attributesArray即可

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {return self.attributesArray;}复制代码

二. 在viewcontroller中使用:

(1)创建瀑布流
//创建瀑布流布局   XRWaterfallLayout *waterfall = [XRWaterfallLayout waterFallLayoutWithColumnCount:3];   //设置各属性的值   waterfall.rowSpacing = 10;   waterfall.columnSpacing = 10;   waterfall.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);   //设置代理,实现代理方法   waterfall.delegate = self; //创建collectionView   self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:waterfall];   self.collectionView.backgroundColor = [UIColor whiteColor];   [self.collectionView registerNib:[UINib nibWithNibName:@"XRCollectionViewCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];   self.collectionView.dataSource = self;   [self.view addSubview:self.collectionView];复制代码
(2)实现代理方法,计算得到item的高
//根据item的宽度与indexPath计算每一个item的高度- (CGFloat)waterfallLayout:(XRWaterfallLayout *)waterfallLayout itemHeightForWidth:(CGFloat)itemWidth atIndexPath:(NSIndexPath *)indexPath {    //根据图片的原始尺寸,及显示宽度,等比例缩放来计算显示高度    XRImage *image = self.images[indexPath.item];    return image.imageH / image.imageW * itemWidth;}复制代码

此时就完成了简单的瀑布流,当然我这篇文章是看了原博主的文章基本上是抄袭过来的,写一遍印象深刻嘛,而且原博主的原代码中还含有懒加载,重写构造方法,重写setter方法等,但是毕竟大神高冷,如果有不懂的小弟为你解答 ??? (再次?)

转载地址:http://lpdha.baihongyu.com/

你可能感兴趣的文章
Web前端开发规范文档
查看>>
安装win2008r2、域控、IIS、证书服务器、部署exchange2010
查看>>
centos6.2安装tomcat
查看>>
利用ansible实现一键化部署 rsync服务
查看>>
nginx根据条件跳转+跳转规则
查看>>
(转载)Javascript异步编程的4种方法
查看>>
ACM suvey
查看>>
Oracle的case 用法
查看>>
Python之路【第二十七篇】:反射
查看>>
敌兵布阵
查看>>
Web.config详解 [转]
查看>>
PHP杂记
查看>>
面试题整理10
查看>>
POP跳转页面,从3号跳回1号,
查看>>
[Android] keytools生成jsk文件以及获取sha1码
查看>>
一道算法题
查看>>
qt.network.ssl: QSslSocket: cannot call unresolved function SSLv23_client_method
查看>>
WM-结汇
查看>>
概述--Nginx集成Vcenter 6.X HTML Console系列之 1--(共4)
查看>>
mysql查询重复
查看>>