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

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

1.通过prepareLayout方法来计算预先计算需要提供的布局信息。
2.通过collectionViewContentSize方法来返回contentSize
3.通过layoutAttributesForElementsInRect: 方法来返回每个cell的信息

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

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

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

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

@interface WKFlowLayout : UICollectionViewLayout

@property (nonatomic, strong) NSMutableDictionary *layoutInformation;
@property (nonatomic) NSInteger maxNumCols; @end static NSUInteger CellWidth = ;
static CGFloat ContentHeight; @implementation WKFlowLayout
{
NSMutableArray *_yOffsets;//存储各列的当前offest
}

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

- (void)prepareLayout
{
_maxNumCols = ;//设置为两列 _yOffsets = [NSMutableArray arrayWithCapacity:_maxNumCols];
for (int i = ; i < _maxNumCols; i++) {
[_yOffsets addObject:@];
} //初始化cell的宽度
CellWidth = self.collectionView.bounds.size.width / _maxNumCols; //事先创建好UICollectionViewLayoutAttributes
_layoutInformation = [NSMutableDictionary dictionary]; NSIndexPath *indexPath;
NSInteger numSections = [self.collectionView numberOfSections];
for(NSInteger section = ; section < numSections; section++){
NSInteger numItems = [self.collectionView numberOfItemsInSection:section];
for(NSInteger item = ; 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);
return contentSize;
} - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *myAttributes = [NSMutableArray arrayWithCapacity:self.layoutInformation.count];
for(NSString *key in self.layoutInformation.allKeys){
UICollectionViewLayoutAttributes *attributes = [self.layoutInformation objectForKey:key]; if(CGRectIntersectsRect(rect, attributes.frame)){
[myAttributes addObject:attributes]; }
}
return myAttributes; }

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

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return NO;
}

示例代码 再附上官方的circleLayout

自定义UICollectionViewLayout 实现瀑布流的更多相关文章

  1. 自定义UICollectionViewLayout之瀑布流

    目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...

  2. iOS自定义UICollectionViewLayout之瀑布流

    目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...

  3. iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合

    1.地图坐标转换那些事 (1)投影坐标系与地理坐标系 地理坐标系使用三维球面来定义地球上的位置,单位即经纬度.但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据.通过投影的方式可以 ...

  4. OC - 29.自定义布局实现瀑布流

    概述 瀑布流是电商应用展示商品通常采用的一种方式,如图示例 瀑布流的实现方式,通常有以下几种 通过UITableView实现(不常用) 通过UIScrollView实现(工作量较大) 通过UIColl ...

  5. iOS---UICollectionView自定义流布局实现瀑布流效果

    自定义布局,实现瀑布流效果 自定义流水布局,继承UICollectionViewLayout 实现一下方法 // 每次布局之前的准备 - (void)prepareLayout; // 返回所有的尺寸 ...

  6. iOS开发进阶 - 自定义UICollectionViewLayout实现瀑布流布局

    移动端访问不佳,请访问我的个人博客 最近项目中需要用到瀑布流的效果,但是用UICollectionViewFlowLayout又达不到效果,自己动手写了一个瀑布流的layout,下面是我的心路路程 先 ...

  7. windowsphone 瀑布流&ui虚拟化

    瀑布流已经有点年代了吧,不过wp上还真是挺少资料的.今天抽空把自己之前搞过的东西写出来,避免大家重复劳动. 一.简单的瀑布流排版加入ui虚拟化. 最近看了 段博琼  ui虚拟化的一篇博文,链接:htt ...

  8. Objectiv-c - UICollectionViewLayout自定义布局-瀑布流

    最近刚写的一个简单的瀑布流. 整体思路可能不是很完善. 不过也算是实现效果了. 高手勿喷 思路: 自定义UICollectionViewLayout实际上就是需要返回每个item的fram就可以了. ...

  9. 自定义UICollectionViewLayout 布局实现瀑布流

    自定义 UICollectionViewLayout 布局,实现瀑布流:UICollectionView和UICollectionViewCell 另行创建,这只是布局文件, 外界控制器只要遵守协议并 ...

随机推荐

  1. Linux下将多个静态库(.a)合并成一个静态库文件(.a)的命令操作,方法一

    .a 文件的结构和.tar文件就没有什么区别. x 命令解出来, a 命令添加, t命令列表 假设A.a, B.a C.a 在/usr/local/lib目录下 mkdir /tmp/libABC c ...

  2. nyoj 1237 最大岛屿(dfs)

    描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的战船黑珍珠1号要征服各个海岛的海盜,最后成为海盗王. 这是一个由海洋.岛屿和海盗组 ...

  3. hdu 1116 Play on Words(欧拉通路)

    Problem Description Some of the secret doors contain a very interesting word puzzle. The team of arc ...

  4. Android Studio Build选项的功能

    再开发过程中出现了如下错误: 无论如何clean,或者删除项目中build文件夹,Rebuild Project还是报错. 解决方案:Make Project 后出现有代码报错.修复代码问题,运行项目 ...

  5. 张冬:OpenPOWER CAPI为什么这么快?(二)

     张冬:OpenPOWER CAPI为什么这么快?(二) PMC公司数据中心存储架构师张冬 有了CAPI的FPGA是怎么做的? 首先认识一下这个体系里的三个角色: AFU(Acceleration ...

  6. 【并查集+拓扑排序】【HDU1811】【Rank of Tetris】

    题意:给你3种关系 A=B,A>B,A<B 问是否排名方式唯一,或者存在矛盾 解 1.读入数据先处理 =号 用并查集的祖先作为代表元素,其他儿子节点都等于跟这个点重叠. 再读入 '< ...

  7. javascript中关于数组的迭代方法

    //都接受3个参数,分别为:值.在数组中的位置.数组对象本身 var num = [2, 1, 5, 4, 2, 1, 6, 8, 19]; //every:若每一项都返回true,则返回true v ...

  8. JavaScript学习笔记——JS中的变量复制、参数传递和作用域链

    今天在看书的过程中,又发现了自己目前对Javascript存在的一个知识模糊点:JS的作用域链,所以就通过查资料看书对作用域链相关的内容进行了学习.今天学习笔记主要有这样几个关键字:变量.参数传递.执 ...

  9. IIS出现Server Application Unavailable的解决办法

    在XP中IIS5.1服务器,运行asp.net出现Server Application Unavailable,经过多次查证,才发现是因为先安装了.net Framework 2.0然后安装IIS,导 ...

  10. 接触CrackMe 第一个

    今天刚接触这个 做了一个简单的. 用Onlydbg加载之后,对GetDlgItemTextA函数下断点,因为程序是在控件上获取数据的. Register输入Name和Serial点击Ok之后,断点响应 ...