UICollectionViewLayout的学习理解

前一篇,讲述学习了UICollectionView的基础用法。这一篇,算是一个进阶学习,关于UICollectionView的Layout自定义学习。因为许多特殊的效果都是通过继承CollectionViewLayout来实现的。UICollectionViewLayout有个亲儿子,名字叫UICollectionViewFlowLayout,适用于线型布局。

UICollectionViewFlowLayout

查看源码,发现UICollectionViewFlowLayout比它的父亲UICollectionViewLayout多了些属性的定义(minimumLineSpacing、minimumInteritemSpacing、headerReferenceSize、footerReferenceSize、sectionInset等等属性),这些都是跟线型布局相关的一些属性定义。所以当展示页面是线型布局时,优先继承UICollectionViewFlowLayout的布局。

UICollectionViewLayout

这次学习研究的重点。打开UICollectionViewLayout.h头文件。仔细查看头文件给我们的有用信息。

UICollectionViewLayout类提供了一个类似于抽象类的形式,来让子类去自定义collection的布局。自定义布局是为满足App复杂需求而产生的一种对Collection的高级操作。

重要的几个方法:


- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;函数默认return NO,返回YES会引起CollectionView重新查询layout的相关信息。当CollectionView的显示范围发生改变的时候,该函数将被调用,如果返回YES,就会重新调用下面的两个方法:- (void)prepareLayout;- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;


- (void)prepareLayout;函数在首次初始化layout实例时会调用,当它再次被调用是在layout Invalidate失效以后,但是在查询layout相关信息之前。子类重写该方法时,必须要调用super的该方法。在这个函数里,主要是对layout布局进行初始化的计算cell的UICollectionViewLayoutAttributes属性,确定即将展示的cell的位置,大小等信息,但是效率偏低,因为一开始可能就有大量的计算需要做。


- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;方法被CollectionView调用来获取Cell的布局信息。返回值是一个数组(数组里面存放着rect范围内所有元素的布局属性),这个方法的返回值决定了rect范围内所有元素的排布(frame)。


- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;方法被CollectionView调用来获取Cell的布局信息。如果你是继承自CollectionViewLayout,就一定要实现这个方法。只有继承CollectionViewLayout才需要,流水布局不需要,因为流水布局内部早已经帮你实现了这个方法。


- (CGSize)collectionViewContentSize;函数用来返回当前自定义CollectionView的ContentSize大小。举个例子:比如当创建垂直瀑布流的时候,需要返回的Size是(瀑布流展示的宽度,瀑布流最底部的Cell的高度)。这样CollectionView就可以在定义的ContentSize的大小范围内滑动展示。官方解释:子类必须重写该方法并返回CollectionView的content的宽度和高度。返回值表示CollectionView内部所有内容的宽高,并不仅仅是当前可见内容的宽高。CollectionView会使用该返回值,去计算自己的ContentSize来决定是否滚动。


- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;函数在手指离开屏幕前调用,因为手指的滑动带给CollectionView滚动惯性,会让CollectionView继续滚动一段距离,而最终停住的位置就是参数proposedContentOffset的值,所以我们应该使用proposedContentOffset的值,而不是手指离开屏幕那瞬间的CollectionView的偏移值。该函数的返回值是CollectionView最终停止时的偏移值,我们可以在函数内部计算是否需要修正最终偏移量。

UICollectionViewLayoutAttributes

这个类主要描述了CollectionView中Cell的位置,大小,透明度等信息。在自定义Cell的时候,需要自己对这些值进行赋值,对位置,大小等进行规定。一个cell对应一个UICollectionViewLayoutAttributes对象。

举个例子

注:例子选自参考文章中的示例,仅作学习参考,理解上述函数的调用。

这里使用了一种图片浏览的线型布局,一种是圆形的图片展示布局。

效果

1.使用自定义的layout,并且创建CollectionView,绑定layout。

效果

2.对CollectionView进行布局上的切换。

效果

3.线型图片浏览布局的layout继承自UICollectionViewFlowLayout,而那个圆圈图片展示的layout继承自UICollectionViewLayout。

4.线型图片浏览布局文件中的几个重要方法:

//对在显示范围内的元素,计算元素UICollectionViewLayoutAttributes,并调整值,最终返回调整Cell的transform后的数组。 效果

//手指松开后,collectionView自由惯性滚动,在停止时,对CollectionView的偏移值修正,始终保持某张图片聚焦放大锁定。 效果

5.圆型图片浏览布局文件中的几个重要方法:

//在prepareLayout方法中把圆形布局图片的attributes数组算出来,调用了[self layoutAttributesForItemAtIndexPath:indexPath];来获取当前indexpath对应的cell的attributes属性,但在layoutAttributesForItemAtIndexPath方法里,又通过UICollectionViewLayoutAttributes的实例方法,获取indexpath位置的attributes属性,需要注意如何获取某个indexPath对应的attributes的方法,代码是:UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];,获取到attrs后,对attrs进行圆形布局计算,修改attrs值,确定对应indexPath位置的cell的位置。代码如下:

效果

参考文章:文章一

文章来自 http://skymonkey.cn/

高能广告区

暂无广告哦=^^=。继续看看其它文章吧!