CollectionView 使用

文章目录
  1. 1. 基本实现注意点
  2. 2. 分析 UICollectionView.h 中的类结构

基本实现注意点

CollectionView 在呈现的数据和用于呈现该数据的视觉元素之间保持严格的区分(view + layout)。

基本使用的过程:

  1. 自己的布局对象:子类化 layout
  2. 自定义 collectionView 中的 item(cell,supplementary views 和 decoration views)
  3. 在layout 的 prepare 方法中计算出所有 attribute(用来修饰 cell,supplementary views 和 decoration views)并缓存在 layout 对象中
    1. 每个 attribute 的indexPath,frame,zIndex ……
    2. 根据 attribute 计算出 collectionViewContentSize
    3. 计算 attribute 的数据可以给 layout 自定义一个 delegate 协议,让他去向 collectionView 拿
  4. layoutAttributesForElementsInRect 获取视图的可见矩形区域中的所有 UICollectionViewLayoutAttributes,类似实现 layoutAttributesForItem:atIndexPathlayoutAttributesForSupplementaryViewOfKind:atIndexPathlayoutAttributesForDecorationViewOfKind:atIndexPath
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 可以使用 binaryTree 算法,将复杂度降到 O(log(n))
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
var visibleLayoutAttributes: [UICollectionViewLayoutAttributes] = []
for attributes in cache {
if attributes.frame.intersects(rect) {
visibleLayoutAttributes.append(attributes)
}
}
return visibleLayoutAttributes
}

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
return cache[indexPath.item]
}
  1. 是否刷新页面

当 collection view 的 bounds 改变时,布局需要告诉 collection view 是否需要重新计算布局。我的猜想是:当 collection view 改变大小时,大多数布局会被作废,比如设备旋转的时候。因此,一个幼稚的实现可能只会简单的返回 YES。虽然实现功能很重要,但是 scroll view 的 bounds 在滚动时也会改变,这意味着你的布局每秒会被丢弃多次。根据计算的复杂性判断,这将会对性能产生很大的影响。
当 collection view 的宽度改变时,我们自定义的布局必须被丢弃,但这滚动并不会影响到布局。幸运的是,collection view 将它的新 bounds 传给 shouldInvalidateLayoutForBoundsChange: 方法。这样我们便能比较视图当前的bounds 和新的 bounds 来确定返回值:

1
2
3
4
5
6
7
8
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
let oldBounds = collectionView?.bounds
if newBounds.width != oldBounds?.width {
return true
}else {
return false
}
}

分析 UICollectionView.h 中的类结构

1
2
3
4
5
6
7
8
@class UICollectionView, UICollectionReusableView, UICollectionViewCell, UICollectionViewLayout, UICollectionViewTransitionLayout, UICollectionViewLayoutAttributes, UITouch, UINib;
@class UIDragItem, UIDragPreviewParameters, UIDragPreviewTarget;
@class UICollectionViewDropProposal, UICollectionViewPlaceholder, UICollectionViewDropPlaceholder;
@class UIContextMenuConfiguration, UITargetedPreview;
@protocol UIContextMenuInteractionCommitAnimating;
@protocol UIDataSourceTranslating, UISpringLoadedInteractionContext;
@protocol UIDragSession, UIDropSession;
@protocol UICollectionViewDragDelegate, UICollectionViewDropDelegate, UICollectionViewDropCoordinator, UICollectionViewDropItem, UICollectionViewDropPlaceholderContext;

引用:

自定义 Collection View 布局