【问题标题】:DecorationView gets resized when AutoSizing cells are enabled in UICollectionViewFlowLayout在 UICollectionViewFlowLayout 中启用 AutoSizing 单元格时,装饰视图会调整大小
【发布时间】:2018-08-06 21:19:57
【问题描述】:

环境:
UICollectionView 看起来像 UITableView
自定义 UICollectionViewFlowLayout 子类来定义frameDecorationView
启用自调整单元格

预期行为:
DecorationView 应作为 UICollectionView 的每个部分的背景放置

观察到的行为:
DecorationView 折叠成任意大小:

似乎UICollectionView 试图计算DecorationView 的自动大小。如果我禁用 Self-Sizing 单元格,则装饰视图将准确放置在预期位置。

有什么方法可以禁用 DecorationView 的 Self-Sizing 吗?

在我的UICollectionViewFlowLayout 子类中,我只需选取该部分中的第一个和最后一个单元格并拉伸背景以填充它们下方的空间。问题是UICollectionView 不尊重那里计算的大小:

override func layoutAttributesForDecorationView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
    guard let collectionView = collectionView else {
      return nil
    }

    let section = indexPath.section
    let attrs = UICollectionViewLayoutAttributes(forDecorationViewOfKind: backgroundViewClass.reuseIdentifier(),
                                                 with: indexPath)
    let numberOfItems = collectionView.numberOfItems(inSection: section)
    let lastIndex = numberOfItems - 1

    guard let firstItemAttributes = layoutAttributesForItem(at: IndexPath(indexes: [section, 0])),
      let lastItemAttributes = layoutAttributesForItem(at: IndexPath(indexes: [section, lastIndex])) else {
        return nil
    }

    let startFrame = firstItemAttributes.frame
    let endFrame = lastItemAttributes.frame

    let origin = startFrame.origin
    let size = CGSize(width: startFrame.width,
                      height: -startFrame.minY + endFrame.maxY)

    let frame = CGRect(origin: origin, size: size)
    attrs.frame = frame
    attrs.zIndex = -1

    return attrs
}

【问题讨论】:

  • 你能在 GitHub 上发布一个演示吗?

标签: ios swift uicollectionview autolayout uicollectionviewflowlayout


【解决方案1】:

在您的单元格的框架已自行调整大小后,您的装饰视图的框架可能没有更新(即无效)。结果是每个装饰视图的宽度保持在其默认大小。

尝试实现此功能,每次该部分中的项目布局无效时,该功能应使每个部分的装饰视图的布局无效:

override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
    let invalidatedSections = context.invalidatedItemIndexPaths?.map { $0.section } ?? []
    let decorationIndexPaths = invalidatedSections.map { IndexPath(item: 0, section: $0) }
    context.invalidateDecorationElements(ofKind: backgroundViewClass.reuseIdentifier(), at: decorationIndexPaths)
    super.invalidateLayout(with: context)
}

【讨论】:

  • 虽然我还没有测试过您的解决方案,但它看起来是最有希望的,我一定会试一试。由于这个问题,我决定暂时不使用自定尺寸单元。
【解决方案2】:

如果您想在 flowLayout 中自定义高度和宽度的大小,您可以使用flowLayoutDelegate 并为每个部分中的每个单元格设置自定义大小等。

extension YourView: UICollectionViewDelegateFlowLayout {

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

            let widthCell: CGFloat = 30.0
            let heightCell: CGFloat = 50
            let size: CGSize = CGSize(width: widthCell, height: heightCell)
            return size
        }
    }

【讨论】:

  • 问题是关于DecorationView,而不是UICollectionViewCell. 这个答案是完全不相关的,因为UICollectionViewDelegateFlowLayout 既没有要求DecorationView 大小的方法,也没有任何其他要求方式。
猜你喜欢
  • 2020-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多