自定义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 另行创建,这只是布局文件, 外界控制器只要遵守协议并 ...
随机推荐
- 消息内容定义XML
<XML> <Title>title</Title> <ContentType>text/plain</ContentType&g ...
- wxpyhon 鼠标事件例子
#encoding:utf-8 import wx import wx.aui class MyFrame(wx.Frame): def __init__(self, *args, **kwargs) ...
- XPath在asp.net中查询XML
.NET Framework 2.0中可以使用System.Xml.XPath命名空间下的类对XML文档进行基于路径的查询,在查询过程中需要构造类似SQL的查询字符串,该字符串遵循XPath语法.它由 ...
- android Handler更新UI
android中经常需要更新界面某个元素的值,但是在主线程中是不可以直接更新主线程的值.这里推荐通过handler机制来更新值. 一Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主 ...
- HDU 1038 - Biker's Trip Odometer
算一下路程和速度... #include <iostream> #include <cstdio> using namespace std; const double p=3. ...
- nginx 学习笔记【持续更新...】
1.如果在安装过程中出现以下错误 需要安装pcre库 解决方案:yum install pcre 2.如果nginx启动提示端口被占用,则停止该端口的服务再启动nginx,一般为httpd服务 解决方 ...
- Nhibernate refers to an unmapped class nhibernate问题的解决(初学者)
最近研究Nhibernate的一些功能,在通过Nhibernate反向建数据库表时遇到了一个问题,refers to an unmapped class:xxxx 通过查阅发现是自己对应的 xxxx ...
- Android周笔记(9.8-14)(持续更新)
本笔记记录一周内的小知识点和一些心学习的Demo. 1.PopupWindow: new 一个activity_pop_window:id为popwindow的Button,id为hello123的T ...
- mysql性能优化学习笔记(6)数据库配置优化&硬件优化
一.操作系统配置优化: 1. 网络方面,修改/etc/sysctl.conf文件,增加tcp支持的队列数,减少断开连接时,资源的回收. 2. 打开文件数的限制.修改 ...
- JSC学习笔记:JavaScriptCore 初识
JSContext/JSValue JSContext是运行JavaScript的上下文环境,是一个全局环境实例:类似于浏览器端的window对象,表示浏览器的窗口:在浏览器中,所有JavaScrip ...