今天,抽空巩固了一下UICollectionview这个UI控件。UICollectionview控件也是开发中经常使用到的一个控件,相比于UITableview,UICollectionview是iOS6之后引入的一个新的UI控件,它和UITableview有着许多的相似之处,但是它是一个比UITableView更加强大的一个视图控件,使用过程中需要实现数据源以及代理方法,其特点如下:
(1)系统自带的流水布局支持水平和垂直两种方式的布局;(2)通过layout配置方式进行布局;(3)collectionview中item的大小和位置可以自定义(4)可以自定义一套layout的布局方案
UICollectionview的初始化方式一般为:
常用的数据源和代理方法:
常用代理方法:
当然UICollectionview的数据源和代理方法远不止这些,我们可以根据功能需要去实现对应的方法。有兴趣的可以查到苹果的相关官方文档。
UICollectionview除了以上的这些初级用法之外,还有一些比较高级的用法。其中最主要的就是自定义collectionview的布局方式,下面我将一一举例说明。直接上代码!!
1.水平线性布局(collectionview水平滚动,实现中间的cell放大),先看看效果
实现方法是:创建一个继承自UICollectionViewFlowLayout类的类LineLayout,然后重写- (void)prepareLayout、- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds、- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect、- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity这几个方法。
- (void)prepareLayout方法主要是一些布局的准备工作,我设置item的内边距就是在这个方法中,此方法只执行一次。注意,一定要写上[super prepareLayout ]
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds方法返回的是一个Bool值,决定着当collectionview的显示范围发生变化的时候,是否需要刷新。默认是No,这里需要设置为yes
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect函数返回的是所有item的布局属性值
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity 此函数的返回值决定了collectionview停止时item的偏移值,在这里主要是让我们滑动结束的时候item能自动调整到中间位置
好了大功告成!!
2.环形布局,同样还是先看看效果图吧
环形布局的layout不需要继承自UICollectionViewFlowLayout,而是集成自UICollectionviewLayout。UICollectionViewFlowLayout是系统自带的一种布局方式,叫做流水布局。因为线性布局里面的很多东西都不需要重写,所以直接继承自UICollectionViewFlowLayout可以省去许多的工作,我们只需要在此基础上做些修改即可;而环形布局则不同,需要我们自己来定义所有的布局属性,以及布局相关的东西。下面就说说具体的实现吧!
同线性布局一样,环形布局也需要实现prepareLayout方法和layoutAttributesForElementsInRect方法。另外,还需要实现- (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath*)indexPath这个方法。layoutAttributesForItemAtIndexPath方法主要是设置indexpath对应的item的布局属性。
prepareLayout的具体实现为:
把获取属性方法放在这里主要是prepareLayout方法只执行一次,所以这些布局属性值计算一次就可以了。如果放在layoutAttributesForElementsInRect方法中,则会反复计算,不利于性能提升。
layoutAttributesForElementsInRect方法就直接返回所有的布局属性就可以了
layoutAttributesForItemAtIndexPath方法的实现(关键 如何计算每个item的center呢?)
好了,到这里环形布局就基本实现了。
3.最后再来看看最后一种比较流行的布局---瀑布流布局,效果图来了
瀑布流布局的layout跟环形布局一样,都需要继承自UICollectionviewLayout。需要实现的方法跟环形布局基本一样,只多了一个collectionViewContentSize方法,实现这个方法才能使collectionview正常滑动。下面且听我一一道来!!
准备工作:首先你需要声明两个可变数组的属性,一个用来存放布局属性的值,一个用来存放每列的高度值。存放高度的数组最好给一个初始值,不然会出现奔溃,报数组越界的问题。
实现:瀑布流布局的prepareLayout和layoutAttributesForElementsInRect一样,没什么可说的,参照上面的就可以了。在这里我要着重说一下layoutAttributesForItemAtIndexPath这个方法的实现。算了,还是直接上代码吧
最后,来设置一下collectionview的contentSize