今天研究了一下自定义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. php信用卡卡号验证函数

    介绍一个php信用卡卡号验证函数,可以验证一个卡号是否是信用卡. function validateCard ($cardnumber){ $cardnumber = preg_replace (&q ...

  2. hdu 5199 Gunner(STL之map,水)

    Problem Description Long long ago, there is a gunner whose name is Jack. He likes to go hunting very ...

  3. hdu 4393 Throw nails(STL之优先队列)

    Problem Description The annual school bicycle contest started. ZL is a student in this school. He is ...

  4. poj 3026 (最小生成树)

    题意:起点开始有超过100个人,总共不会超过100个外星人,问把所有的外星人都搜出来花的最小时间.一条路径上的时间跟人数是无关的,只跟路径长度有关. 思路:刚开始人都在起点,当派一定人数去最近的外星人 ...

  5. MatLab实现FFT与功率谱

    FFT和功率谱估计 用Fourier变换求取信号的功率谱---周期图法 clf; Fs=1000; N=256;Nfft=256;%数据的长度和FFT所用的数据长度 n=0:N-1;t=n/Fs;%采 ...

  6. 在 WinForm 中打开页面采用POST方式传参http。可以多个参数传递,返回json字符串

    //调用方法 Dictionary<string, string> postData = new Dictionary<string, string>(); postData. ...

  7. js 中的for...in循环

    in:其左边是一个字符串或可以转换成字符串,右边是一个对象或数组 例:var person={firstname:"Bob", lastname:"Kin"}; ...

  8. weiphp 微信公众号用程序来设置指定内容消息回复业务逻辑操作

    微信公众号机器人回复设置 在公众号插件里面的Robot- Model- weixinAddonModel.php里面的 reply设置 reply($dataArr,$keywordArr) 解析方法 ...

  9. LPC基础教程-Lpc程序和编程环境 mudos 加载原理

    编程环境 通常我们所见到的Mud大多是LpMud.LpMuds使用Unix的指令和文件结构.如果你对Unix有所了解,那么LpMud中的一些指令和它的文件结构与普通的Unix基本一样.如果你从未使用过 ...

  10. linux系统下安全管理

    1.引导程序安全 linux系统的root密码是很容易破解的,当然前提是你没有设置引导程序密码,如GRUB或LILO,为了防止通过引导程序破译root密码,强烈建 议设置GRUB或LILO的引导密码, ...