石工布局(Masonty Layout)是指集合视图中的物件模仿石灰浆墙,常用来在二维空间中平铺大量物件。
现在创建一个UICollectionViewLayout的子类并添加到工程中,布局子类中主要有两个职责,首先是计算集合视图中每个物件的frame,其次是计算集合视图整个内容的大小。
子类需要覆盖的方法:
1.- (void)prepareLayout;//布局之前被调用,在这个方法中计算所有item的frame
2.- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;//返回给定矩形中所有物件的属性
3.- (CGSize)collectionViewContentSize; //返回集合视图内容的大小
在本例中,物件的宽度应该有两个变量决定,列数和item之间的间距,这种情况下,引入变量numberOfColums和itemSpacing。物件的高度则由数据源提供一个变量,可以声明一个委托对象,在委托中,声明一个collectionView:Layout:heightForItemAtIndexPath:协议方法。
接下来就是计算每个item的frame。
1.计算item的宽度
2.计算Item的x坐标
其中currentColumn为item所在的列。
3.计算item的y和高度
通过调用刚才写的协议方法来的得到高度,在加上在这一列前面所有item的高度来得到y,这里使用了lastYValueForColum字典来维护了布局中所有列的高度。
开始先从字典lastYValueForColumn中获取y值,然后给y加上高度itemSpacing再保存到lastYValueForColumn中。计算完成后,就保存到layoutInfo中,在下一个方法layoutAttributesForElementsInRect:中调用到layoutInfo。当集合视图滚动时,系统会调用这个方法并传递可见的矩形区域。用CGRectIntersectsRect方法可以把这个区域中的item筛选出来,返回一个装有这些item的数组。代码实现如下:
接下来的任务就是计算集合视图内容的大小,y值已经存在lastYValueForColumn字典中,我们扩遍历这个字典中找到每列中最大y值作为集合视图的contentSize的height。这个方法涉及到所有类型的视图,也就是cell,supplementary views和decoration views。如果选择忽略传入的矩形,并且为collection view中的所有视图返回布局属性。这将对性能产生非常坏的影响,特别是可见cell远少于所有cell数量的时候,collection view和布局对象将会为那些不可见的视图做额外不必要的工作。
最后,当 collection view 的 bounds 改变时,布局需要告诉 collection view 是否需要重新计算布局。scroll view 的 bounds 在滚动时也会改变,这意味着你的布局每秒会被丢弃多次。根据计算的复杂性判断,这将会对性能产生很大的影响。
当 collection view 的宽度改变时,我们自定义的布局必须被丢弃,但这滚动并不会影响到布局。collection view 将它的新 bounds 传给shouldInvalidateLayoutForBoundsChange:方法。这样我们便能比较视图当前的bounds 和新的 bounds 来确定返回值:
好了,小工告成。喜欢的点个赞,不喜欢的打赏几块吧。