前言
UICollectionView由于可以custom layout的原因使其非常强大,一个layout能玩出花来。之前有一个非常有名的第三方库iCarousel,效果也很不错,但是由于在性能上还是稍差些。后来就慢慢被UICollectionView取代了。
进入正题,我做自定义layout的时候就是看raywenderlich上面的教程,我觉得非常好,就用raywenderlich的demo来记录一下。demo在这里。
layout和data的关系
核心布局处理
自定义layout,有三个方法必须重写
- func prepareLayout() 在这个方法里计算好每个Item的position和CollectionView的size并缓存
- func collectionViewContentSize() -> CGSize 返回CollectionView的ContentSize
- func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?在这个方法里返回某个特定区域的布局的属性
计算布局的属性
获取cell各个控件的高度以及header的高度,使用代理1
2
3
4
5
6
7
8
9
10
11
12@objc protocol WeiouDetailCollectionViewLayoutDelegate {
Method to ask the delegate for the height of the image
func collectionView(collectionView:UICollectionView, heightForPhotoAtIndexPath indexPath:NSIndexPath , withWidth:CGFloat) -> CGFloat
Method to ask the delegate for the height of the annotation text
func collectionView(collectionView: UICollectionView, heightForAnnotationAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -> CGFloat
func collectionView(collectionView: UICollectionView, heightForShortAddrAtIndexPath indexPath: NSIndexPath, withWidth width: CGFloat) -> CGFloat
for header
func collectionViewHeightForHeadrPicture(collectionView: UICollectionView, withWidth width: CGFloat) -> CGFloat
}
1 | override func prepareLayout() { |
还是上图吧,一图胜千言
在layout中,没有列的概念,就是很机械的按照规则排列下去,主要Y值的计算。虚拟了一个列的概念column = column >= (numberOfColumns - 1) ? 0 : ++column
理解一下
返回布局的ContentSize
1 | //需要返回的是整个collectionView高度,包括header, footer, cell |
重写layoutAttributesForElementsInRect(_:)
1 | override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { |
有header footer的话一定要加上!!!
关于获取高度的代理方法
主要是图片,纯文本,富文本的高度,方法Google一下就知道了,很简单。富文本的高度计算坑比较大,另开一篇说吧。。。
更新约束
最后,在自定义的cell,header里调用
1 | -(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes |
更新约束,然后,大功告成!