最近调研瀑布流,在gitHub上下了个Demo发现它的所有视图都是用Main.storyboard拖的, 自己研究半天没研究明白;

然后就又找了一个Demo, 它的视图全是手打的, 但是实现的方法不太好,就将这俩Demo结合了一下:

用了gitHub的实现原理 和 另一个Demo的视图.

实现瀑布流最重要的一步就是重写UICollectionViewFlowLayout类, 下面就简单介绍一下实现原理

本方法实现的仅是高度不一样, 宽度是根据屏宽平均分的;

当创建UICollectionView的UICollectionViewFlowLayout属性时,给它传进去了两个属性: 列数, 和需要显示的Model数组 (这里是商品model(图片,价钱))

WaterfallFlowLayout.h

//  WaterfallFlowLayout.h
@interface WaterfallFlowLayout : UICollectionViewFlowLayout // 总列数
@property (nonatomic, assign) NSInteger columnCount; // 商品数据数组
@property (nonatomic, strong) NSArray *goodsArray; @end

在.m文件里就根据这两个属性计算每个frame的大小, 用一个数组记录每列的高度, 每次计算frame时就将它放到最短列下面:

仅为计算item属性数组  和 itemSize, 然后在layoutAttributesForElementsInRect返回了该数组,就算是改变了每个item的frame了

<span style="font-family: Arial, Helvetica, sans-serif;">//  WaterfallFlowLayout.m</span>
#import "WaterfallFlowLayout.h"
#import "Good.h" @interface WaterfallFlowLayout ()
// 所有item的属性的数组
@property (nonatomic, strong) NSArray *layoutAttributesArray;
@end @implementation WaterfallFlowLayout /**
* 布局准备方法 当collectionView的布局发生变化时 会被调用
* 通常是做布局的准备工作 itemSize.....
* UICollectionView 的 contentSize 是根据 itemSize 动态计算出来的
*/
- (void)prepareLayout {
// 根据列数 计算item的宽度 宽度是一样的
CGFloat contentWidth = self.collectionView.bounds.size.width - self.sectionInset.left - self.sectionInset.right; //减去分区的边框
CGFloat marginX = self.minimumInteritemSpacing; //最小左右间距
CGFloat itemWidth = (contentWidth - marginX * (self.columnCount - 1)) / self.columnCount; // 计算布局属性
[self computeAttributesWithItemWidth:itemWidth];
} #pragma mark 根据itemWidth计算布局属性
- (void)computeAttributesWithItemWidth:(CGFloat)itemWidth { // 定义一个列高数组 记录每一列的总高度
CGFloat columnHeight[self.columnCount];
// 初始化
for (int i = 0; i < self.columnCount; i++) {
columnHeight[i] = self.sectionInset.top;
} // 遍历 goodsList 数组计算相关的属性
NSMutableArray *attributesArray = [NSMutableArray arrayWithCapacity:self.goodsArray.count]; //因为item数是跟当前的商品数一样的 每次改变都动态计算一遍
for (NSInteger i = 0; i < self.goodsArray.count; i++) {
Good *good = self.goodsArray[i];
// 建立布局属性
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
// 获得当前item的布局属性
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
// 找出最短列号
NSInteger column = [self shortestColumn:columnHeight];
// X值
CGFloat itemX = (itemWidth + self.minimumInteritemSpacing) * column + self.sectionInset.left;
// Y值 = 当前列的总高度
CGFloat itemY = columnHeight[column];
// 等比例缩放 计算item的高度
CGFloat itemH = good.h * itemWidth / good.w;
// 设置frame
attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemH);
[attributesArray addObject:attributes]; //!!!!!!!!
self.itemSize = CGSizeMake(itemWidth, itemH); // 累加当前列高
columnHeight[column] += itemH + self.minimumLineSpacing; }
// 给属性数组设置数值
self.layoutAttributesArray = attributesArray.copy;
} #pragma mark 找出columnHeight数组中最短列号 追加数据的时候追加在最短列中
- (NSInteger)shortestColumn:(CGFloat *)columnHeight { CGFloat min = CGFLOAT_MAX;
NSInteger column = 0;
// 循环列高数组
for (int i = 0; i < self.columnCount; i++) {
if (columnHeight[i] < min) {
min = columnHeight[i];
column = i;
}
}
return column;
} /**
* 跟踪效果:当到达要显示的区域时 会计算所有显示item的属性
* 一旦计算完成 所有的属性会被缓存 不会再次计算
* @return 返回布局属性(UICollectionViewLayoutAttributes)数组
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
// 直接返回计算好的布局属性数组
return self.layoutAttributesArray;
}

一下是Demo下载地址:

http://download.csdn.net/detail/margaret_mo/9417425

WaterfallFlowLayout瀑布流用重写UICollectionViewFlowLayout类实现的更多相关文章

  1. Android瀑布流照片墙实现,体验不规则排列的美感

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10470797 传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在 ...

  2. CollectionView水平和竖直瀑布流的实现

    最近在项目中需要实现一个水平的瀑布流(即每个Cell的高度是固定的,但是长度是不固定的),因为需要重写系统 UICollectionViewLayout中的一些方法通过计算去实现手动布局,所以本着代码 ...

  3. iOS瀑布流实现(Swift)

    这段时间突然想到一个很久之前用到的知识-瀑布流,本来想用一个简单的方法,发现自己走入了歧途,最终只能狠下心来重写UICollectionViewFlowLayout.下面我将用两种方法实现瀑布流,以及 ...

  4. 自定义UICollectionViewLayout之瀑布流

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

  5. iOS自定义UICollectionViewLayout之瀑布流

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

  6. iOS横向瀑布流的封装

    前段时间, 做一个羡慕, 需要使用到瀑布流! 说道瀑布流, 或许大家都不陌生, 瀑布流的实现也有很多种! 从scrollView 到 tableView 书写的瀑布流, 然后再到2012年iOS6 苹 ...

  7. iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

    上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewControlle ...

  8. IOS 瀑布流

    本篇博客应该算的上CollectionView的高级应用了,从iOS开发之窥探UICollectionViewController(一)到今天的(五),可谓是由浅入深的窥探了一下UICollectio ...

  9. 详细分享UICollectionView的自定义布局(瀑布流, 线性, 圆形…)

    前言: 本篇文章不是分享collectionView的详细使用教程, 而是属于比较’高级’的collectionView使用技巧, 阅读之前, 我想你已经很熟悉collectionView的基本使用, ...

随机推荐

  1. 传智播客--数据绑定--INotifyPropertyChanged(小白内容)

    INotifyPropertyChanged一般在数据绑定的时候使用. InotifyPropertyChanged是.net内置的接口,数据绑定时会检测DataContext是否实现了Inotify ...

  2. python统计某一个进程名所占用的内存

    设计思路: 通过python,执行cmd中tasklist命令,获取要统计的进程的相关信息:通过正则表达式,查找出进程名称.进程pid.内存使用,然后打印出来. 作为pythoner,有时候需要统计p ...

  3. .Net 转战 Android 4.4 日常笔记(8)--常见事件响应及实现方式

    在Andrioid开发中,常见的事件如下 单击事件 OnClickListener 长按事件 OnLongClickListener 滑动事件 OnTouchListenner 键盘事件 OnKeyL ...

  4. Web APi之过滤器执行过程原理解析【二】(十一)

    前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...

  5. ZOJ Problem Set - 1109 Language of FatMouse

    这道题目最让人头疼的就是该题的input怎么结束,因为它要求输入一个空行的时候则一串字符串输入结束,这就不得不让人绕个弯来解决这个问题. (注:本人习惯于使用C中的字符串操作,但是用到map要求使用s ...

  6. 去百度API的百度地图准确叠加和坐标转换的解决方案研究

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 目前项目上如果要使用百度地图,得加载百度的开发包,然后通过百 ...

  7. 【集合框架】JDK1.8源码分析之LinkedList(七)

    一.前言 在分析了ArrayList了之后,紧接着必须要分析它的同胞兄弟:LinkedList,LinkedList与ArrayList在底层的实现上有所不同,其实,只要我们有数据结构的基础,在分析源 ...

  8. 加入一个线程:join

    在启动一个线程之后调用该线程的join()方法,会使该线程先执行,该线程执行完成后,再执行调用该线程的线程. 例如如下的任务: public class LiftOff extends Thread ...

  9. 从零开始,搭建博客系统MVC5+EF6搭建框架(5),博客详情页、留言、轮播图管理、右侧统计博文

    一.博客系统进度回顾 上一遍博客介绍到,系统已经实现到了发布以及前台布局展示,接下来就是实现一些,详情页,留言.轮播图管理.右侧博文统计信息实现. 二.博客系统详情页实现 2.1先来看看详情页展示的效 ...

  10. LINQ to SQL语句(15)之String

    LINQ to SQL支持以下String方法.但是不同的是默认情况下System.String方法区分大小写.而SQL则不区分大小写. 1.字符串串联(String Concatenation) v ...