在 UICollectionViewFlowLayout 中启用 AutoSizing 单元格时,DecorationView 会调整大小
DecorationView gets resized when AutoSizing cells are enabled in UICollectionViewFlowLayout
环境:
UICollectionView
看起来像 UITableView
自定义 UICollectionViewFlowLayout 子类来定义 DecorationView
的 frame
已启用自调整单元格
预期行为:
DecorationView
应作为 UICollectionView
每个部分的背景
观察到的行为:
DecorationView
折叠成任意大小:
似乎 UICollectionView
试图计算 DecorationView
的自动大小。如果我禁用自调整单元格,则装饰视图将准确放置在预期位置。
有什么方法可以为 DecorationView
禁用自我调整大小?
在我的 UICollectionViewFlowLayout
子类中,我简单地获取该部分中的第一个和最后一个单元格并拉伸背景以填充它们下面的 space。问题是 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
}
在单元格的框架 self-sized 之后,装饰视图的框架可能没有更新(即无效)。结果是每个装饰视图的宽度都保持默认大小。
尝试实现这个功能,每次该部分中的项目布局无效时,它应该使每个部分的装饰视图布局无效:
override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
let invalidatedSections = context.invalidatedItemIndexPaths?.map { [=10=].section } ?? []
let decorationIndexPaths = invalidatedSections.map { IndexPath(item: 0, section: [=10=]) }
context.invalidateDecorationElements(ofKind: backgroundViewClass.reuseIdentifier(), at: decorationIndexPaths)
super.invalidateLayout(with: context)
}
环境:
UICollectionView
看起来像 UITableView
自定义 UICollectionViewFlowLayout 子类来定义 DecorationView
的 frame
已启用自调整单元格
预期行为:
DecorationView
应作为 UICollectionView
观察到的行为:
DecorationView
折叠成任意大小:
似乎 UICollectionView
试图计算 DecorationView
的自动大小。如果我禁用自调整单元格,则装饰视图将准确放置在预期位置。
有什么方法可以为 DecorationView
禁用自我调整大小?
在我的 UICollectionViewFlowLayout
子类中,我简单地获取该部分中的第一个和最后一个单元格并拉伸背景以填充它们下面的 space。问题是 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
}
在单元格的框架 self-sized 之后,装饰视图的框架可能没有更新(即无效)。结果是每个装饰视图的宽度都保持默认大小。
尝试实现这个功能,每次该部分中的项目布局无效时,它应该使每个部分的装饰视图布局无效:
override func invalidateLayout(with context: UICollectionViewLayoutInvalidationContext) {
let invalidatedSections = context.invalidatedItemIndexPaths?.map { [=10=].section } ?? []
let decorationIndexPaths = invalidatedSections.map { IndexPath(item: 0, section: [=10=]) }
context.invalidateDecorationElements(ofKind: backgroundViewClass.reuseIdentifier(), at: decorationIndexPaths)
super.invalidateLayout(with: context)
}