UICollectionView-使用Flow Layout

Using the Flow Layout

你可以在collection view中使用UICollectionViewFlowLayout类来组织item。Flow layout实现了一个基于线的布局,就是说布局对象在一条线性路径尽可能多的放置cell。当布局对象到达了当前行的末尾是,会另起一行。
UICollectionView-使用Flow Layout_第1张图片

配置flow layout的步骤:

  • 创建一个flow layout对象,并把它指派给collection view
  • 配置cell色高度和宽度
  • 设置line和item的space
  • 如果你需要section headers或者section footers,指定它们的大小。
  • 设置layout滑动的方向

自定义Flow Layout的属性(Customizing the Flow Layout Attributes)

例如可以使用itemSize属性来设置cell的大小。
如果你想动态的变化item的spacing或者size,你可以使用UICollectionViewDelegateFlowLayout协议。

在Flow Layout指定Item的大小

如果collection view中的item都是同样的大小,可以通过flow layout对象的itemSize 属性来指定长宽。
如果你想为cell指定不同的大小,你需实现collection view代理的collectionView:layout:sizeForItemAtIndexPath: 方法。
UICollectionView-使用Flow Layout_第2张图片

指定Items 和 Lines间的间隔

使用flow layout,你可以指定同一行item之间的间隔,也可以指定连续行之间的最小空间大小。要记住的是,你提供的只是最小间隔(minimum spacing)。
UICollectionView-使用Flow Layout_第3张图片
UICollectionView-使用Flow Layout_第4张图片

你可以使用 flow layout对象的minimumLineSpacing和minimumInteritemSpacing属性来指定间隔大小,也可以使用代理方法collectionView:layout:minimumLineSpacingForSectionAtIndex:和collectionView:layout:minimumInteritemSpacingForSectionAtIndex:来指定间隔大小。

使用Section Inset来调整内容的间距

UICollectionView-使用Flow Layout_第5张图片

由于inset减少了布局cell所用的空间,你可以使用它们来限制一行的cell数量。

创建自定义布局(Creating Custom Layouts)

理解布局的过程(Understanding the Core Layout Process)

当collection view 需要布局信息的时候,它会请求布局对象提供信息。你可以调用invalidateLayout 方法来告诉collection view更新它的布局。
在布局的工程中,collection view 会调用特定的方法。这些方法可以计算item的位置,和提供给collection view所需的信息。其它的方法也可能会被调用,这些方法在布局的工程中调用的顺序如下:

  1. 使用prepareLayout方法预先计算需要提供给布局的信息
  2. 使用collectionViewContentSize方法,返回根据你初步计算的整个内容区域的整体尺寸
  3. 使用layoutAttributesForElementsInRect:方法,返回在指定区域的cell和view的属性。

UICollectionView-使用Flow Layout_第6张图片

prepareLayout来计算cell和view在布局中位置。至少,你应该要得到content area的大小,这是在step2中返回给collection view的。
collection view使用这个content size来配置scroll view。例如,如果计算的大小在水平和垂直方向超过了当前设备屏幕的大小,那么scroll view就可以在两个方向上滚动。
基于当前滚动的位置,collection view会调用layoutAttributesForElementsInRect:方法来获取在特定区域的cell和view的属性。
在滚动的过程中,collection view可以使你当前的布局无效。用户滑动时,collection view调用布局对象的shouldInvalidateLayoutForBoundsChange:方法,如果这个方法返回YES,则会使当前的布局无效。

创建布局属性Creating Layout Attributes

布局的属性对象是UICollectionViewLayoutAttributes类。使用如下的方法来创建UICollectionViewLayoutAttributes类的实例:

  • layoutAttributesForCellWithIndexPath:
  • layoutAttributesForSupplementaryViewOfKind:withIndexPath:
  • layoutAttributesForDecorationViewOfKind:withIndexPath:
按需求提供布局属性
  • layoutAttributesForItemAtIndexPath:
  • layoutAttributesForSupplementaryViewOfKind:atIndexPath:
  • layoutAttributesForDecorationViewOfKind:atIndexPath:

使用自定义的布局

self.collectionView.collectionViewLayout = [[MyCustomLayout alloc] init];

使自定义布局更吸引人

Elevating Content Through Supplementary Views

所有的supplementary view都必须继承自UICollectionReusableView 类:

  1. 注册supplementary view,使用registerClass:forSupplementaryViewOfKind:withReuseIdentifier:或者 registerNib:forSupplementaryViewOfKind:withReuseIdentifier:方法
  2. 在data source中,实现collectionView:viewForSupplementaryElementOfKind:atIndexPath:方法。因为这些view是复用的,调用dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:方法来复用。
  3. 为supplementary view创建布局属性对象
  4. 在layoutAttributesForElementsInRect:方法中返回属性数组
  5. 实现layoutAttributesForSupplementaryViewOfKind:atIndexPath:方法来特定的supplementary view 的属性对象
Including Decoration Views in Your Custom Layouts

与cells和supplementary view不同,decoration view只提供visual content,并独立于data source之外。

添加decoration view到布局中,按如下的方式:

  1. 使用布局对象的registerClass:forDecorationViewOfKind: 或者registerNib:forDecorationViewOfKind: 方法来注册 decoration view。要记住的是,注册decoration view是在布局对象内,而不是在data source
  2. 在布局对象的layoutAttributesForElementsInRect: 方法中创建属性
  3. 在布局对象中实现layoutAttributesForDecorationViewOfKind:atIndexPath:方法,返回decoration views的属性
  4. 可选,实现initialLayoutAttributesForAppearingDecorationElementOfKind:atIndexPath:和finalLayoutAttributesForDisappearingDecorationElementOfKind:atIndexPath:方法来处理decoration view出现和消失的动画。

Making Insertion and Deletion Animations More Interesting

如下图所示,collection view起初只有3个cell。当一个新的cell被插入时,collection view请求布局对象提供被插入cell的初始属性。在这个例子中,布局对象把cell的初始位置设置为collection view的中心,并把cell的alpha值设为0,来隐藏它。在动画的过程中,新的cell慢慢出现并移动到右下角。

UICollectionView-使用Flow Layout_第7张图片

- (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath {
   UICollectionViewLayoutAttributes* attributes = [self layoutAttributesForItemAtIndexPath:itemIndexPath];
   attributes.alpha = 0.0;

   CGSize size = [self collectionView].frame.size;
   attributes.center = CGPointMake(size.width / 2.0, size.height / 2.0);
   return attributes;
}

Note:上面的代码中,当一个cell插入时,所有的cell,即3个已经展示的cell都会从collection view的中间pop out ,当第四个cell插入的时候。为了仅仅使被插入的cell动画,应当查看item的indexPath是否与prepareForCollectionViewUpdates:方法中传递的item的indexPath是否匹配。否者的话,在initialLayoutAttributesForAppearingItemAtIndexPath:中调用super方法。

Improving the Scrolling Experience of Your Layout

当滚动相关的触摸事件发生时,scroll view会通过当前的speed和减速度来,决定最后的位置。当collection view明确了位置,它会请求调用布局对象的targetContentOffsetForProposedContentOffset:withScrollingVelocity: 方法来确定是否修改位置。因为它调用这个方法的时候,内容还在移动,所以你的自定义的布局能够影响滚动内容的最终位置。

UICollectionView-使用Flow Layout_第8张图片

使用自定义布局Tips

  • 使用prepareLayout方法来创建和存储UICollectionViewLayoutAttributes对象。
  • 避免继承UICollectionView
  • 一定不能在layoutAttributesForElementsInRect:方法中调用UICollectionView的visibleCells 方法。

参考教程

  • TUTORIAL: Creating custom layouts for UICollectionView
  • TUTORIAL: Using UICollectionView with UICollectionViewFlowLayout
  • Implementing UICollectionViewLayout
  • UICollectionView custom layout tutorial
  • WWDC 2012 Session笔记——219 Advanced Collection Views and Building Custom Layouts
  • WWDC 2012 Session笔记——205 Introducing Collection Views

你可能感兴趣的:(UICollectionView-使用Flow Layout)