如何使用Swift向UICollectionViewFlowLayout添加其他补充视图?

时间:2017-03-12 09:59:09

标签: ios swift uicollectionview uicollectionviewlayout uicollectionreusableview

Collection View Programming Guide for iOS中所述,如果要向Flow Layout添加新的补充视图或装饰视图,则必须继承UICollectionViewFlowLayout。

我需要帮助才能在Swift 3中实施以下步骤:

  

标准流布局类仅支持节标题和节页脚视图,不支持装饰视图。要支持其他补充和装饰视图,您至少需要覆盖以下方法:

           

在layoutAttributesForElementsInRect:方法中,您可以调用super来获取单元格的布局属性,然后为指定矩形中的任何新补充视图或装饰视图添加属性。使用其他方法按需提供属性。

我想实现的目标:

  • 每个项目上方的一个补充视图
  • 委托类似referenceSizeForHeaderInSection的方法来定义集合视图控制器内的新补充视图的大小(return CGSize.zero,如果不应该是"项目标题")
  • 准确计算的内容大小
  • 使用每个项目插入,更新和删除补充视图的动画

更新

我知道这个问题的定义过于宽泛。但是在Devon和一些自己的想法的帮助下,我找到了一个适合我的解决方案。

  1. 子类 UICollectionViewFlowLayout

    class SBCollectionViewFlowLayout: UICollectionViewFlowLayout { … }

  2. 覆盖layoutAttributesForElements(in rect: CGRect)以向每个单元格添加其他补充视图。

    // Check if there already valid layout attributes
    guard var layoutAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
    
    // Try to append new supplementary view to each cell
    // ────────────────────────────────────────────────────────────      
    
    for attributes in layoutAttributes where attributes.representedElementCategory == .cell {
        if let supplementaryAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindDateSeparator, at: attributes.indexPath) {
            layoutAttributes.append(supplementaryAttributes)
        }
    }
    
    return layoutAttributes
    
  3. 覆盖layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath)以计算集合视图中新补充视图的位置。

    switch elementKind {
    
    case UICollectionElementKindDateSeparator:
    
        // Return if there is no collection view or delegate
        guard let delegate = self.collectionView?.delegate as? SBCollectionViewDelegateFlowLayout else { return nil }
    
        // Get the dynamic size of from the delegate
        let size = delegate.collectionView!(self.collectionView!, layout: self, referenceSizeForSeparatorAt: indexPath)
    
        // Return if there the size is (0, 0)
        if size == CGSize.zero { return nil }
    
        // Create new layout attributes for the separator
        // ════════════════════════════════════════════════════════════
    
        let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: elementKind, with: indexPath)
    
        if let itemAttributes = layoutAttributesForItem(at: indexPath) {
    
            // Position supplementary view at top left edge of the cell
            // ────────────────────────────────────────────────────────────
    
            attributes.frame = CGRect(x: itemAttributes.frame.origin.x,
                                      y: itemAttributes.frame.origin.y,
                                      width:  size.width,
                                      height: size.height)
    
            // Increase the item’s position on the z axis
            // to be sure that the item appear on top of the cell.
            attributes.zIndex = 1
        }
    
        return attributes
    
    default:
        // If it is not a date separator, return attributes from flow layout
        return super.layoutAttributesForSupplementaryView(ofKind: elementKind, at: indexPath)
    }
    
  4. "扩展和#34; UICollectionViewDelegateFlowLayout 向代表询问新标题的大小。

    public protocol SBCollectionViewDelegateFlowLayout: UICollectionViewDelegateFlowLayout  {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForSeparatorAt indexPath: IndexPath) -> CGSize
    }
    
  5. TL; DR

    这个想法不是将附加的补充视图插入到集合视图中,然后重新计算所有项目,而是在相应的单元格顶部添加补充视图。向单元格添加动态顶部填充非常重要,补充视图不会覆盖单元格内的任何内容。

    我希望这可以帮助其他人解决类似问题!

0 个答案:

没有答案