UICollectionView 总结

这个视图是我遇到的 UIView 里面最复杂的吧。。。感觉学好了这个,UIScrollView 和 UITableView 都不算啥了。。。

UICollectionView有两个主要的特点:

其一:和tableView一样,即提供数据的UICollectionViewDataSource以及处理用户交互的UICollectionViewDelegate;

其二,对于cell的样式和组织方式,由于collectionView比tableView要复杂得多,因此没有按照类似于tableView的style的方式来定义,而是专门使用了一个类来对collectionView的布局和行为进行描述,这就是UICollectionViewLayout。这不仅是collectionView和tableView的最重要求的区别,也是整个UICollectionView的精髓所在。

1)基本视图

最简单的 UICollectionView 就是一个 GridView,可以以多列的方式将数据进行展示。标准的UICollectionView包含三个部分,它们都是UIView的子类:

  • Cells:用于展示内容的主体,对于不同的cell可以指定不同尺寸和不同的内容
  • Supplementary Views 追加视图 (类似Header或者Footer)
  • Decoration Views 装饰视图 (用作背景展示,只在 UICollectionViewLayout 中提供)

2)视图的注册和重用

相比 UITableView 有两个主要变化:一是加入了对某个 Class 的注册,这样即使不用提供nib而是用代码生成的 view 也可以被接受为 cell 了;二是不仅只是 cell,supplementaryView也可以用注册的方法绑定初始化了。在对collection view的重用ID注册后,就可以像UITableView那样简单的写cell配置了:

在使用 UICollectionView 的时候,初始化一个 layout 给这个 UICollectionView,并且注册相应的 cell 和 supplementaryView,这样在之后的重用方法中,就没有必要像 UITableView 一样判断是否有 cell 或 supplementaryView——要是在重用队列里没有可用的cell的话,runtime将自动帮我们生成并初始化一个可用的cell.

3)cell

UICollectionView 的 cell 相对 UITableView 简单,由下而上分别为:

  • cell :本身作为容器 view;
  • backgroundView:cell 的背景;
  • selectedBackgroundView:cell 被选中时的背景
  • contentView:自定义内容会添加到这个 view 上。

4)UICollectionViewLayout

负责了将各个cell、Supplementary View和Decoration Views进行组织,为它们设定各自的属性——layoutAttributes。

Layout决定了UICollectionView是如何显示在界面上的。在展示之前,一般需要生成合适的UICollectionViewLayout子类对象,并将其赋予CollectionView的collectionViewLayout属性。

Apple为我们提供了一个最简单可能也是最常用的默认layout对象:UICollectionViewFlowLayout。Flow Layout简单说是一个直线对齐的layout,最常见的Grid View形式即为一种Flow Layout配置。

UICollectionViewFlowLayout 的重要属性有:

  • itemSize:定义了每一个item的大小。通过设定itemSize可以全局地改变所有cell的尺寸,也可以定制尺寸
  • spacing:指定 item 之间间距和每一行之间的间距,可以全局设置或者定制间距
  • scrollDirection:确定 scroll view 的方向,将影响 Flow Layout 的基本方向和由 header 及 footer 确定的 section 之间的宽度
  • header 和 footer:同样可以全局设置或者定制。根据滚动方向不同,高和宽中只有一个会起作用:垂直滚动时section间宽度为该尺寸的高,而水平滚动时为宽度起作用
  • sectionInset:section 的缩进

5)UICollectionViewLayoutAttributes——这个类包含的属性有:

1 @property (nonatomic) CGRect frame
2 @property (nonatomic) CGPoint center
3 @property (nonatomic) CGSize size
4 @property (nonatomic) CATransform3D transform3D
5 @property (nonatomic) CGFloat alpha
6 @property (nonatomic) NSInteger zIndex
7 @property (nonatomic, getter=isHidden) BOOL hidden

UICollectionViewLayoutAttributes的实例中包含了诸如边框,中心点,大小,形状,透明度,层次关系和是否隐藏等信息。和DataSource的行为十分类似,当UICollectionView在获取布局时将针对每一个indexPath的部件(包括cell,追加视图和装饰视图),向其上的UICollectionViewLayout实例询问该部件的布局信息(在这个层面上说的话,实现一个UICollectionViewLayout的时候,其实很像是封装一个delegate,之后的例子中会很明显地看出),这个布局信息,就以UICollectionViewLayoutAttributes的实例的方式给出。

6)自定义UICollectionViewLayout

UICollectionViewLayout的功能为向UICollectionView提供布局信息,不仅包括cell的布局信息,也包括追加视图和装饰视图的布局信息。实现一个自定义layout的常规做法是继承UICollectionViewLayout类,然后重载下列方法:

//返回collectionView的内容的尺寸
-(CGSize)collectionViewContentSize
//返回rect中的所有的元素的布局属性,一个包含UICollectionViewLayoutAttributes的NSArray
-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
//UICollectionViewLayoutAttributes可以是cell,追加视图或装饰视图的信息,通过不同的UICollectionViewLayoutAttributes初始化方法可以得到不同类型的UICollectionViewLayoutAttributes:
layoutAttributesForCellWithIndexPath:
layoutAttributesForSupplementaryViewOfKind:withIndexPath:
layoutAttributesForDecorationViewOfKind:withIndexPath:
//返回对应于indexPath的位置的cell的布局属性
-(UICollectionViewLayoutAttributes )layoutAttributesForItemAtIndexPath:(NSIndexPath )indexPath
//返回对应于indexPath的位置的追加视图的布局属性,如果没有追加视图可不重载
-(UICollectionViewLayoutAttributes )layoutAttributesForSupplementaryViewOfKind:(NSString )kind atIndexPath:(NSIndexPath *)indexPath
//返回对应于indexPath的位置的装饰视图的布局属性,如果没有装饰视图可不重载
-(UICollectionViewLayoutAttributes * )layoutAttributesForDecorationViewOfKind:(NSString)decorationViewKind atIndexPath:(NSIndexPath )indexPath
//当边界发生改变时,是否应该刷新布局。如果YES则在边界变化(一般是scroll到其他地方)时,将重新计算需要的布局信息。
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds

5)自定义 UICollectionViewLayout

在初始化一个UICollectionViewLayout实例后,会有一系列准备方法被自动调用,以保证layout实例的正确:

首先,-(void)prepareLayout将被调用,默认下该方法什么没做,但是在自己的子类实现中,一般在该方法中设定一些必要的layout的结构和初始需要的参数等。

之后,-(CGSize) collectionViewContentSize将被调用,以确定collection应该占据的尺寸。注意这里的尺寸不是指可视部分的尺寸,而应该是所有内容所占的尺寸。collectionView的本质是一个scrollView,因此需要这个尺寸来配置滚动行为。

接下来-(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect被调用,这个没什么值得多说的。初始的layout的外观将由该方法返回的UICollectionViewLayoutAttributes来决定。

另外,在需要更新layout时,需要给当前layout发送 -invalidateLayout,该消息会立即返回,并且预约在下一个loop的时候刷新当前layout,这一点和UIView的setNeedsLayout方法十分类似。在-invalidateLayout后的下一个collectionView的刷新loop中,又会从prepareLayout开始,依次再调用-collectionViewContentSize和-layoutAttributesForElementsInRect来生成更新后的布局。

posted @ 2016-03-28 19:47  xiayao.zeng  阅读(177)  评论(0编辑  收藏  举报