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

上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看iOS开发之窥探UICollectionViewController(二) –详解CollectionView各种回调。UICollectionView之所以强大,是因为其具有自定义功能,这一自定义就不得了啦,自由度非常大,定制的高,所以功能也是灰常强大的。本篇博客就不使用自带的流式布局了,我们要自定义一个瀑布流。自定义的瀑布流可以配置其参数: 每个Cell的边距,共有多少列,Cell的最大以及最小高度是多少等。

一.先入为主

先来看一下不同配置参数下运行后的效果吧,每张截图的列数和Cell之间的边距都有所不同,瀑布流的列数依次为2,3,8。有密集恐惧证的童鞋就不要看这些运行效果图了,真的会看晕的。下面这些运行效果就是修改不同的配置参数来进行布局的。看图吧,关于瀑布流的效果就不啰嗦了。以下的效果就是使用自定义布局做的,接下来将会介绍一下其实现原理。

二. UICollectionViewLayout

在介绍上述效果实现原理之前,需要介绍一下UICollectionViewLayout。UICollectionView的自定义功能就是自己去实现UICollectionViewLayout的子类,然后重写相应的方法来实现Cell的布局,先介绍一下需要重写的方法,然后再此方法上进行应用实现上述瀑布流。好,废话少说,干活走起。

1.布局预加载函数

当布局首次被加载时会调用prepareLayout函数,见名知意,就是预先加载布局,在该方法中可以去初始化布局相关的数据。该方法类似于视图控制器的ViewDidLoad方法,稍后回用到该方法。

2.内容滚动范围

下方是定义ContentSize的方法。该方法会返回CollectionView的大小,这个方法也是自定义布局中必须实现的方法。说白了,就是设置ScrollView的ContentSize,即滚动区域。

3. 下方四个方法是确定布局属性的,下方第一个方法返回一个数组,该数组中存放的是为每个Cell绑定的UICollectionViewLayoutAttributes属性,便于在下面第二个方法中去定制每个Cell的属性。第三个方法就是根据indexPath来获取Cell所绑定的layoutAtrributes, 然后去更改UICollectionViewLayoutAttributes对象的一些属性并返回,第四个是为Header View或者FooterView来定制其对应的UICollectionViewLayoutAttributes,然后返回。

4.UICollectionViewLayoutAttributes

下方是UICollectionViewLayoutAttributes常用的属性,你可以在上面第二个方法中去为下方这些属性赋值,为Cell定制属于自己的Attributes。由下方的属性就对自定义布局的的强大,在本篇博客中只用到了下方的一个属性,那就是frame。

三. UICollectionViewLayout的应用

经过上面的简单介绍,想必对UICollectionViewLayout有一定的了解吧,UICollectionViewLayout中还有好多方法,以后用到的时候在给大家介绍。接下来要使用自定义布局来实现瀑布流。我们需要在UICollectionViewLayout的子类中实现相应的布局方法,因为UICollectionViewLayout是虚基类,是不能直接被实例化的,所以我们需要新建一个布局类,这个布局类继承自UICollectionViewLayout。然后去实现上述方法,给每个Cell定制不同的UICollectionViewLayoutAttributes。好了还是拿代码说话吧。

1.重写prepareLayout方法去初始化一些数据,该方法在CollectionView重新加载时只会调用一次,所以把一些参数的配置,计算每个Cell的宽度,每个Cell的高度等代码放在预处理函数中。在该函数中具体调用的函数如下所示:

2.返回内容的范围,即为CollectionView设定ContentSize。ContentSize的Width就是屏幕的宽度,而ContentSize的高度是一列中最后一个Cell的Y坐标加上其自身高度的最大值。在此函数中会调用求CellY数组中的最大值。具体实现代码如下:

3.下面的方法是为每个Cell去绑定一个UICollectionViewLayoutAttributes对象,并且以数组的形式返回,在我们的自定义瀑布流中,我们只自定义了Cell的frame,就可以实现我们的瀑布流,UICollectionViewLayoutAttributes的其他属性我们没有用到,由此可以看出自定义Cell布局功能的强大。

4. 通过下述方法设定每个Cell的UICollectionViewLayoutAttributes对象的参数,为了实现瀑布流所以我们只需要设置每个Cell的frame即可。每个cell的frame的确定是以列来定的,有所在列的上个Cell的Y坐标来确定下个cell的位置。瀑布流实现关键点如下:

(1)Cell宽度计算:如果瀑布流的列数和Cell的Padding确定了,那么每个Cell的宽度再通过屏幕的宽度就可以计算出来了。

(2)Cell高度计算:通过随机数生成的高度

(3)Cell的X轴坐标计算:通过列数,和Padding,以及每个Cell的宽度很容易就可以计算出每个Cell的X坐标。

(4)Cell的Y轴坐标计算:通过Cell所在列的上一个Cell的Y轴坐标,Padding, 和 上一个Cell的高度就可以计算下一个Cell的Y坐标,并记录在Y坐标的数组中了。

5. initData方法主要是对数据进行初始化,在本篇博客中为了先实现效果,我们暂且把数据给写死。下篇博客会在本篇博客中的基础上进行优化和改进,这些配置参数都会在Delegate中提供,便于灵活的去定制属于你自己的瀑布流。本篇博客中Demo的配置项先写死就OK了,还是那句话,下篇博客中会给出一些相应的代理,来定制我们的瀑布流。

6.下方的方法是根据Cell的列数来求出Cell的宽度。因为Cell的宽度都是一样的,每个Cell的间隔也是一定的。例如有5列Cell, 那么Cell中间的间隔就有4(5-1)个,那么每个Cell的宽度就是屏幕的宽度减去所有间隔的宽度,再除以列数就是Cell的宽度。如果没听我啰嗦明白的话,直接看代码吧,并不复杂。每个Cell的宽度和间隔确定了,那么每个Cell的X轴坐标也就确定了。代码如下:

7. 根据Cell的最小高度和最大高度来利用随机数计算每个Cell的高度,把每个Cell的高度记录在数组中,便于Cell加载时使用。具体代码如下:

8.初始化Cell的Y轴坐标数组,因为是瀑布流,瀑布流的特点是每列中Cell的X轴坐标是相同的,我们只需要根据本列上一个Cell的Y轴坐标来确定本列中将要插入Cell的Y轴坐标,所有我们需要维护一个每列当前Cell的Y轴坐标数组。其初始化方法如下:

9.下面的方法是求Cell的Y轴坐标数组的最大值,因为在Cell都加载完毕后,Cell数组中最大值就是CollectionView的ContentSize的Height的值。

10.下方代码是求CellY数组中的第一个最小值的索引,因为求出这个CellY数组中的第一个Cell最新值得索引就是Cell应该插入的列。

自定义集合视图控制器布局第一阶段就先到这,下篇博客会在此基础上进一步开发。把上述写死的配置参数,通过Delegate提供,使其在UICollectionView可进行配置,其配置方式类似于UICollectionViewDelegateFlowLayout的代理方法。

上述代码gitHub分享地址:https://github.com/lizelu/CustomCollectionViewLayout

打赏支持我写出更多好文章,谢谢!

打赏作者

打赏支持我写出更多好文章,谢谢!

1 2 收藏 评论

关于作者:青玉伏案

乐于分享,广交善缘。走在技术的路上,一直在学习中。(http://www.cnblogs.com/ludashi/)https://github.com/lizeluQQ群:310800319 个人主页 · 我的文章 · 3 ·    

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部