如何为 UICollectionViewCompositionalLayout 中的不同部分设置多个背景视图
Posted
技术标签:
【中文标题】如何为 UICollectionViewCompositionalLayout 中的不同部分设置多个背景视图【英文标题】:How to set up Multiple Background View for different Sections in UICollectionViewCompositionalLayout 【发布时间】:2020-11-26 18:20:04 【问题描述】:我正在尝试为我的部分提供不同的背景颜色/图像,但发现很难在 createCompositionalLayout() 中设置两个不同的背景视图。
下面是两个背景视图组件和部分。在布局创建方法中注册类/nib 的示例有很多,但这只是为所有部分创建一个背景视图。
在 createCompositionalLayout() 中有一个用于返回 NSCollectionLayoutSection(部分)的开关,但要为每个部分返回已注册的背景视图布局是我的障碍。
func createCompositionalLayout() -> UICollectionViewLayout
let layout = UICollectionViewCompositionalLayout sectionIndex, layoutEnvironment in
guard let sectionKind = SectionBack(rawValue: sectionIndex) else return nil
let section = self.sections[sectionIndex]
switch section.type
case "mediumTable":
return self.createMediumTableSection(using: section)
case "smallTable":
return self.createSmallTableSection(using: section)
default:
return self.createFeaturedSection()
return layout
**Red backgroundview**
let backgroundItem = NSCollectionLayoutDecorationItem.background(elementKind: "background")
let backgroundInset: CGFloat = 8
backgroundItem.contentInsets = NSDirectionalEdgeInsets(top: backgroundInset, leading:
backgroundInset, bottom: backgroundInset, trailing: backgroundInset)
layoutSection.decorationItems = [backgroundItem]
let layout = UICollectionViewCompositionalLayout(section: layoutSection)
layout.register(RedBackgroundSupplementaryView.self, forDecorationViewOfKind:
"background")
func createMediumTableSection(using section: Section) -> NSCollectionLayoutSection
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.33))
let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
layoutItem.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 5)
let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .fractionalWidth(0.55))
let layoutGroup = NSCollectionLayoutGroup.vertical(layoutSize: layoutGroupSize, subitems: [layoutItem])
let layoutSection = NSCollectionLayoutSection(group: layoutGroup)
layoutSection.orthogonalScrollingBehavior = .groupPagingCentered
let layoutSectionHeader = createSectionHeader()
layoutSection.boundarySupplementaryItems = [layoutSectionHeader]
return layoutSection
func createSmallTableSection(using section: Section) -> NSCollectionLayoutSection
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(0.2))
let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize)
layoutItem.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 0)
let layoutGroupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.93), heightDimension: .estimated(200))
let layoutGroup = NSCollectionLayoutGroup.vertical(layoutSize: layoutGroupSize, subitems: [layoutItem])
let layoutSection = NSCollectionLayoutSection(group: layoutGroup)
let layoutSectionHeader = createSectionHeader()
layoutSection.boundarySupplementaryItems = [layoutSectionHeader]
return layoutSection
【问题讨论】:
【参考方案1】:问题出在这对线:
layout.register(RedBackgroundSupplementaryView.self, forDecorationViewOfKind:"background")
layout.register(BlackBackgroundSupplementaryView.self, forDecorationViewOfKind:"background")
你不能同时拥有它。 kind
字符串是您将如何识别您想要的:
let backgroundItem = NSCollectionLayoutDecorationItem.background(elementKind: "background")
但是你只有一个kind
字符串。您的第二个注册出现并取代了第一个。您需要使用两种不同的背景颜色注册两种不同的装饰视图类型。
【讨论】:
好的,假设我只有一个注册类,对于当前设置的背景视图,有没有办法为一个部分而不是整个布局实现它? 不要给其他部分任何装饰? 意思是如何使用我拥有的当前设置来构建代码或实现。 此时您已将“当前设置”编辑为我无法理解的,因此我无法回答。我已经回答了您最初回答的问题;如果您想要两个不同部分的两种不同装饰,按照您最初显示代码的方式,您需要两个不同的kind
字符串。【参考方案2】:
所以此时你已经改变了你的问题。在评论中,您说:
假设我只有一个注册类,对于当前设置的背景视图,有没有办法为一个部分而不是整个布局实现它?
当然,虽然我不知道“使用当前设置”是什么意思,因为你现在拥有的代码(当前设置)显然是错误的,否则你会得到你想要的结果。
无论如何,这很简单:在您的部分提供程序功能中,只给那个部分一个装饰视图,不要给任何其他部分一个装饰视图!
这是一个集合视图的截图,其中只有第一部分有背景装饰视图:
代码很简单:
private func createLayout() -> UICollectionViewLayout
let lay = UICollectionViewCompositionalLayout ix, env in
// ... create item and group (omitted) ...
let section = NSCollectionLayoutSection(group: group)
// ... create header (omitted) ...
// okay, create decoration!
let deco = NSCollectionLayoutDecorationItem.background(elementKind: "background")
deco.contentInsets = NSDirectionalEdgeInsets(top: 5, leading: 5, bottom: 5, trailing: 5)
if ix == 0 // only add the decoration for section 0
section.decorationItems = [deco]
return section
return lay
【讨论】:
但是看看我的代码。在您的评论中,您正在调用 UICollectionViewCompositionalLayout 初始化程序init(section:)
。但如果你这样做,所有部分都将是相同的。你必须做你看到 me 做的事:致电init(sectionProvider:)
。这样,您可以为每个部分做一些不同的,就像我在我的代码中所做的那样。当您说 let layout = UICollectionViewCompositionalLayout sectionIndex, layoutEnvironment
时,您确实使用了该初始化程序,因此您有了一个良好的开端。以上是关于如何为 UICollectionViewCompositionalLayout 中的不同部分设置多个背景视图的主要内容,如果未能解决你的问题,请参考以下文章
如何为 RecyclerView 设置 onItemClickListener? [复制]