自定义UICollectionViewLayout 实现瀑布流
今天研究了一下自定义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 实现瀑布流的更多相关文章
- 自定义UICollectionViewLayout之瀑布流
目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...
- iOS自定义UICollectionViewLayout之瀑布流
目标效果 因为系统给我们提供的 UICollectionViewFlowLayout 布局类不能实现瀑布流的效果,如果我们想实现 瀑布流 的效果,需要自定义一个 UICollectionViewLay ...
- iOS开发笔记15:地图坐标转换那些事、block引用循环/weak–strong dance、UICollectionviewLayout及瀑布流、图层混合
1.地图坐标转换那些事 (1)投影坐标系与地理坐标系 地理坐标系使用三维球面来定义地球上的位置,单位即经纬度.但经纬度无法精确测量距离戒面积,也难以在平面地图戒计算机屏幕上显示数据.通过投影的方式可以 ...
- OC - 29.自定义布局实现瀑布流
概述 瀑布流是电商应用展示商品通常采用的一种方式,如图示例 瀑布流的实现方式,通常有以下几种 通过UITableView实现(不常用) 通过UIScrollView实现(工作量较大) 通过UIColl ...
- iOS---UICollectionView自定义流布局实现瀑布流效果
自定义布局,实现瀑布流效果 自定义流水布局,继承UICollectionViewLayout 实现一下方法 // 每次布局之前的准备 - (void)prepareLayout; // 返回所有的尺寸 ...
- iOS开发进阶 - 自定义UICollectionViewLayout实现瀑布流布局
移动端访问不佳,请访问我的个人博客 最近项目中需要用到瀑布流的效果,但是用UICollectionViewFlowLayout又达不到效果,自己动手写了一个瀑布流的layout,下面是我的心路路程 先 ...
- windowsphone 瀑布流&ui虚拟化
瀑布流已经有点年代了吧,不过wp上还真是挺少资料的.今天抽空把自己之前搞过的东西写出来,避免大家重复劳动. 一.简单的瀑布流排版加入ui虚拟化. 最近看了 段博琼 ui虚拟化的一篇博文,链接:htt ...
- Objectiv-c - UICollectionViewLayout自定义布局-瀑布流
最近刚写的一个简单的瀑布流. 整体思路可能不是很完善. 不过也算是实现效果了. 高手勿喷 思路: 自定义UICollectionViewLayout实际上就是需要返回每个item的fram就可以了. ...
- 自定义UICollectionViewLayout 布局实现瀑布流
自定义 UICollectionViewLayout 布局,实现瀑布流:UICollectionView和UICollectionViewCell 另行创建,这只是布局文件, 外界控制器只要遵守协议并 ...
随机推荐
- 【C/C++】Linux下system()函数引发的错误
http://my.oschina.net/renhc/blog/54582 [C/C++]Linux下system()函数引发的错误 恋恋美食 恋恋美食 发布时间: 2012/04/21 11:3 ...
- poj3934Queue(dp)
题目链接: 啊哈哈,点我点我 题意: 有n个幼儿园的孩纸.然后从中找出m对孩子可以让他们看到两方,这样以便他们交流.. 思路: 首先能够考虑把n-1个人已经排成了m-2对.那么仅仅须要把这个最矮的随便 ...
- button属性值
AccessibilityObject 取得指定給控制項的 AccessibleObject. (繼承自 Control). AccessibleDefaultActionDescription 取得 ...
- JavaScript中的setAttribute用法
我们经常需要在JavaScript中给Element动态添加各种属性,这可以通过使用setAttribute()来实现,这就涉及到了浏览器的兼容性问题. setAttribute(string nam ...
- IE下图片切换的时候,图片总是切换不成功---根本问题是IE缓存图片
作为WEB设计者,为了在网页展示上加强用户体验,经常会利用图象载入显示状态方法,这自然需要Image对象的onload事件. 在firefox浏览器下完成开发后,可是在IE浏览器中进行调试总不能被调用 ...
- SQL语句优化(转摘)
(1) 选择最有效率的表名顺序(只在基于规则的seo/' target='_blank'>优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最 ...
- C# 启动EXE文件及带启动参数EXE
(一).先制作一个带启动参数的EXE文件. 步骤: 1.定义全局私有变量:private string[] s = new string[1]; //这里为了简单起见,只做一个参数 2. 在窗体的 ...
- 贝叶斯网络基础(Probabilistic Graphical Models)
本篇博客是Daphne Koller课程Probabilistic Graphical Models(PGM)的学习笔记. 概率图模型是一类用图形模式表达基于概率相关关系的模型的总称.概率图模型共分为 ...
- [Poco库]使用经验
1. Link错误 在Windows平台下使用时link报错 "CreateProcess is not defined"的解决GetEnvironmentVariable / S ...
- 转 jquery插件--241个jquery插件—jquery插件大全
241个jquery插件—jquery插件大全 jquery插件jqueryautocompleteajaxjavascriptcoldfusion jQuery由美国人John Resig创建,至今 ...