自定义UICollectionViewLayout 实现瀑布流

摘要:
同时,以下三种方法可用于传输布局信息、contentSize、单元格信息等。

今天研究了一下自定义UICollectionViewLayout。 看了看官方文档,要自定义UICollectionViewLayout,需要创建一个UICollectionViewLayout的子类。同时,可以通过一下3个方法传递布局信息、contentSize、cells的信息等。

一、继承UICollectionViewLayout,重写以下方法

1.通过prepareLayout方法来计算预先计算需要提供的布局信息。
2.通过collectionViewContentSize方法来返回contentSize
3.通过layoutAttributesForElementsInRect: 方法来返回每个cell的信息
自定义UICollectionViewLayout 实现瀑布流第1张

二、创建UICollectionViewLayoutAttributes,创建的方法有一下三种

1.layoutAttributesForCellWithIndexPath:
2.layoutAttributesForSupplementaryViewOfKind:withIndexPath:
3.layoutAttributesForDecorationViewOfKind:withIndexPath:

其中,layoutAttributesForCellWithIndexPath:方法创建cell的属性,layoutAttributesForSupplementaryViewOfKind:withIndexPath:创建补充视图的属性,如header、footer,layoutAttributesForDecorationViewOfKind:withIndexPath:创建修饰视图的属性

基础知识介绍完了,接下讲具体示例 创建一个UICollectionViewLayout的子类WKFlowLayout,

@interfaceWKFlowLayout : UICollectionViewLayout

@property (nonatomic, strong) NSMutableDictionary *layoutInformation;
@property (nonatomic) NSInteger maxNumCols;

@end

static NSUInteger CellWidth = 100;  
staticCGFloat ContentHeight;

@implementationWKFlowLayout
{
    NSMutableArray *_yOffsets;//存储各列的当前offest
}

接下来在prepareLayout预先计算布局信息

- (void)prepareLayout
{
    _maxNumCols = 2;//设置为两列
_yOffsets =[NSMutableArray arrayWithCapacity:_maxNumCols];
    for (int i = 0; i < _maxNumCols; i++) {
        [_yOffsets addObject:@0];
    }

    //初始化cell的宽度
    CellWidth = self.collectionView.bounds.size.width /_maxNumCols;

    //事先创建好UICollectionViewLayoutAttributes
    _layoutInformation =[NSMutableDictionary dictionary];

    NSIndexPath *indexPath;
    NSInteger numSections =[self.collectionView numberOfSections];
    for(NSInteger section = 0; section < numSections; section++){
        NSInteger numItems =[self.collectionView numberOfItemsInSection:section];
        for(NSInteger item = 0; item < numItems; item++){
            indexPath =[NSIndexPath indexPathForItem:item inSection:section];
            UICollectionViewLayoutAttributes *attributes =[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

            NSInteger col = indexPath.item %_maxNumCols;

            WKFlowLayoutDataSource *ds =self.collectionView.dataSource;

            NSNumber *height =ds.dataSource[indexPath.row];
            attributes.frame = CGRectMake(col *CellWidth, [_yOffsets[col] floatValue], CellWidth, [height floatValue]);
            CGFloat yOffset;

            yOffset = [_yOffsets[col] floatValue] +[height floatValue];
            NSLog(@"yOffset:%f col:%ld", yOffset, (long)col);

            _yOffsets[col] =@(yOffset);

            [_layoutInformation setObject:attributes forKey:indexPath];
            //计算滚动高度
            ContentHeight =MAX(ContentHeight, CGRectGetMaxY(attributes.frame));
        }
    }
}

剩下的代码

-(CGSize)collectionViewContentSize
{
    CGFloat contentWidth =self.collectionView.bounds.size.width;

    CGSize contentSize =CGSizeMake(contentWidth, ContentHeight);
    returncontentSize;
}

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSMutableArray *myAttributes =[NSMutableArray arrayWithCapacity:self.layoutInformation.count];
    for(NSString *key inself.layoutInformation.allKeys){
        UICollectionViewLayoutAttributes *attributes =[self.layoutInformation objectForKey:key];

            if(CGRectIntersectsRect(rect, attributes.frame)){
                [myAttributes addObject:attributes];

        }
    }
    returnmyAttributes;

}

以上就是主要的实现代码了,需要注意的是,在prepareLayout中预先算出所有的布局信息适用于cell个数小于1000,超过之后在耗时就过长了,用户体验不好,同时需要在- (BOOL)shouldInvalidateLayoutForBoundsChange:方法中返回NO,此方法表示不需要再滚动过程中不停的调用prepareLayout

-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    returnNO;
}

示例代码 再附上官方的circleLayout

免责声明:文章转载自《自定义UICollectionViewLayout 实现瀑布流》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Qt笔记——MOC(莫克)Flutter App打包配置(android平台)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL基本语法总结

一、基础 模式定义了数据如何存储、存储什么样的数据以及数据如何分解等信息,数据库和表都有模式。 主键的值不允许修改,也不允许复用(不能使用已经删除的主键值赋给新数据行的主键)。 SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/...

R语言学习——图形初阶之折线图与图形参数控制

plot()是R中为对象作图的一个泛型函数(它的输出将根据所绘制对象类型的不同而变化);plot(x,y,type="b")表示将x置于横轴,y置于纵轴,绘制点集(x,y),然后使用线段将其连接;type="b"表示同时绘制点和线,使用help(plot)可以查看其它选项。 实例: > dev.new() # 打开一个新的图形窗口NULL> d...

js实现瀑布流以及加载效果

一、瀑布流是个啥?   瀑布流,是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。   最早采用瀑布流布局的网站是Pinterest,逐渐在国内流行开来,比如我们熟知的百度图片的布局,在“很久”以前,百度图片还是需要一页一页的点击进行查看更多图片,而现在的瀑布流布局使用户查找图片...

python数据处理中内存优化的一些tricks

1、读入数据时,pandas默认int类型为int64,未采用最省类型方式读取,可通过以下方式优化内存 1)数值型能用更低内存类型保存就转换为更低内存类型 2) 将object类型转换为category类型 category 类型在底层使用整型数值来表示该列的值,而不使用原值.Pandas用一个字典来构建这些整型数据到原数据的映射关系.当一列只包含有有限...

leetcode 36 有效的数独 哈希表 unordered_set unordersd_map 保存状态 leetcode 37 解数独

leetcode 36 感觉就是遍历。 保存好状态,就是各行各列还有各分区divide的情况 用数组做。 空间小时间大 class Solution { public: bool isValidSudoku(vector<vector<char>>& board) { int row[9][9]={...

Linux col命令详解

Linux col命令 Linux col命令用于过滤控制字符。 在许多UNIX说明文件里,都有RLF控制字符。当我们运用shell特殊字符">"和">>",把说明文件的内容输出成纯文本文件时,控制字符会变成乱码,col指令则能有效滤除这些控制字符。 用法 col [-bfpx] [-l nline] 参数 -b 过滤掉所有的控制字符,包...