UICollectionView使用UICollectionViewFlowLayout删除分节符

Jim*_* Xu 7 objective-c uikit ios uicollectionviewlayout swift

我有一个数据集,该数据集分为多个部分,但是,我想在collectionView中显示该数据集,而各部分之间不会出现中断。这是我要实现的目标的说明:

Instead of:
0-0 0-1 0-2
0-3
1-0 1-1
2-0
3-0

I want:
0-0 0-1 0-2
0-3 1-0 1-1
2-0 3-0
Run Code Online (Sandbox Code Playgroud)

我意识到解决方案可能在于自定义UICollectionViewLayout子类,但是我不确定如何实现这样的目标。

谢谢

Mar*_*moy 3

您是正确的,您需要继承 UICollectionViewLayout 的子类。在开始之前要理解的本质是,您需要至少计算集合视图中每个单元格的位置和大小。UICollectionViewLayout 只是提供该信息的结构化方式。你得到了结构,但你必须自己提供其他一切。

有 4 个方法需要重写:

  • 准备
  • 无效布局
  • 布局属性ForItemAtIndexPath
  • 布局属性ForElementsInRect

一个技巧是将布局属性缓存在查找表(字典)中:

var cachedItemAttributes = [IndexPath: UICollectionViewLayoutAttributes]()
Run Code Online (Sandbox Code Playgroud)

prepare中,您计算​​collectionView中每个indexPath的布局属性:

override func prepare() {
    super.prepare()
    calculateAttributes()
}
Run Code Online (Sandbox Code Playgroud)

invalidateLayout中,您重置缓存的布局属性并重新计算它们:

override func invalidateLayout() {
    super.invalidateLayout()
    cachedItemAttributes = [:]
    calculateAttributes()
} 
Run Code Online (Sandbox Code Playgroud)

layoutAttributesForItemAtIndexPath中,您使用查找表返回正确的布局属性:

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    return cachedItemAttributes[indexPath]
}
Run Code Online (Sandbox Code Playgroud)

layoutAttributesForElementsInRect中,您可以过滤查找表以查找指定矩形内的元素:

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    return cachedItemAttributes.filter { rect.intersects($0.value.frame) }.map { $0.value }
}
Run Code Online (Sandbox Code Playgroud)

最后一个难题是布局属性的实际计算。这里我只提供伪代码:

func calculateAttributes() {
    // For each indexpath (you can get this from the collectionView property using numberOfSections and numberOfItems:inSection )
    // calculate the frame, i.e the origin point and size of each cell in your collectionView and set it with UICollectionViewLayoutAttributes.frame
    // There are many other properties on UICollectionViewLayoutAttributes that you can tweak for your layout, but frame is a good starting point from which you can start experimenting.
    // Add the layout attributes to the lookup table
    // end loop
}
Run Code Online (Sandbox Code Playgroud)

为了回答您的问题,这里是计算每个单元格位置的伪代码:

// If width of cell + current width of row + spacing, insets and margins exceeds the available width
// move to next row.
// else
// cell origin.x = current width of row + interitem spacing
// cell origin.y = number of rows * (row height + spacing)
// endif
Run Code Online (Sandbox Code Playgroud)

如果您需要可配置自定义布局,则可以在可用签名足够的情况下使用 UICollectionViewDelegateFlowLayout,或者定义您自己的继承自 UICollectionViewDelegateFlowLayout 或 UICollectionViewDelegate 的布局。因为您的协议继承自 UICollectionViewDelegateFlowLayout,而 UICollectionViewDelegateFlowLayout 本身又继承自 UICollectionViewDelegate,因此您可以将其直接设置为视图控制器中的 collectionView 委托。在自定义集合视图布局中,您只需将委托从 UICollectionViewDelegate 转换为自定义协议即可使用它。请记住处理转换失败或委托未实现协议方法的情况。