UICollectionViewLayout:仅将装饰视图添加到特定单元格

Posted

技术标签:

【中文标题】UICollectionViewLayout:仅将装饰视图添加到特定单元格【英文标题】:UICollectionViewLayout: add DecorationView only to specific cells 【发布时间】:2018-04-13 10:06:08 【问题描述】:

我开发了一个自定义 CollectionViewLayout,它使用DecorationView 来显示单元格后面的阴影。

但是,我只想将此装饰添加到某些单元格。 UICollectionViewvertical,但它可能在单元格内包含嵌入的 horizontal UICollectionView。嵌入UICollectionView 的单元格不应该被装饰,如图所示:

这是我用来添加阴影的代码。 UICollectionViewLayout 没有提供如何检索单元格的类的方法,因此它可以决定是否添加阴影:

  override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
    let parent = super.layoutAttributesForElements(in: rect)
    guard let attributes = parent, !attributes.isEmpty else 
      return parent
    

    let sections = attributes.map$0.indexPath.section
    let unique = Array(Set(sections))


    // Need to detect, which sections contain an embedded UICollectionView and exclude them from the UNIQUE set


    let backgroundShadowAttributes: [UICollectionViewLayoutAttributes] = unique.compactMap section in
      let indexPath = IndexPath(item: 0, section: section)
      return self.layoutAttributesForDecorationView(ofKind: backgroundViewClass.reuseIdentifier(),
                                                    at: indexPath)
    

    return attributes + backgroundShadowAttributes + separators
  

有什么方法可以有条件地指定,哪些视图应该被装饰?

【问题讨论】:

为什么不能用阴影创建自定义单元格类并在 UICollectionViewLayout 中创建适当的填充? 还有更复杂的情况,当UICollectionView 看起来像UITableView 并且阴影渲染正确。在这种情况下,将阴影附加到 UICollectionViewCell 不起作用:i.stack.imgur.com/hVKoY.png 【参考方案1】:

完成以下代码: 直接询问 DataSource 是否为特定部分显示阴影的协议:

protocol SectionBackgroundFlowLayoutDataSource 
  func shouldDisplayBackgroundFor(section: Int) -> Bool

并利用func layoutAttributesForElements(in rect: CGRect) 方法中的协议:

  override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? 
    let parent = super.layoutAttributesForElements(in: rect)
    guard let attributes = parent, !attributes.isEmpty else 
      return parent
    

    attributes.forEach(configureRoundCornersAttributes)

    // Display shadows for every section by default
    var sectionsWithShadow = Set(attributes.map$0.indexPath.section)
    if let dataSource = collectionView?.dataSource as? SectionBackgroundFlowLayoutDataSource 
    // Ask DataSource for sections with shadows, if it supports the protocol
      sectionsWithShadow = sectionsWithShadow.filterdataSource.shouldDisplayBackgroundFor(section: $0)
    

    let backgroundShadowAttributes: [UICollectionViewLayoutAttributes] = sectionsWithShadow.compactMap section in
      let indexPath = IndexPath(item: 0, section: section)
      return self.layoutAttributesForDecorationView(ofKind: backgroundViewClass.reuseIdentifier(),
                                                    at: indexPath)
    

    return attributes + backgroundShadowAttributes + separators
  

func shouldDisplayBackgroundFor(section: Int) -> Bool 可能比cellForItemAtIndexPath 返回更快,因为它不需要完整的单元配置。

【讨论】:

感谢您的回答。是否可以为您的 collectionviewflowlayout 子类发布整个代码,因为我正在尝试做完全相同的事情并且我正在努力!

以上是关于UICollectionViewLayout:仅将装饰视图添加到特定单元格的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionViewLayout 示例

UICollectionViewLayout 教程

我应该继承啥 UICollectionViewLayout 或 UICollectionViewFlowLayout

使用缓存的 UICollectionViewLayoutAttributes 子类化 UICollectionViewLayout

UICollectionViewLayout - 2 列中的 3 个单元格

为啥将 UICollectionViewLayout 分配给 UICollectionView 后 UICollectionViewCells 不再可见?