如何使用组合布局为不同部分设置不同的背景?
Posted
技术标签:
【中文标题】如何使用组合布局为不同部分设置不同的背景?【英文标题】:How can I set different backgrounds for different sections using compositional layout? 【发布时间】:2021-08-12 03:15:39 【问题描述】:我想使用组合布局为集合视图中的不同部分设置不同的背景。
目前我正在使用NSCollectionLayoutDecorationItem.background
设置部分的背景。然而,这种类型的视图不会像补充视图或单元格那样出队或回收。初始化后我无法对其进行更改,也无法自己初始化它。
我想使用作为我从后端检索的用户数据的一部分的颜色或背景图像,因此在编译时我不知道颜色或图像。
有什么方法可以动态设置部分的背景图片或颜色?
【问题讨论】:
不使用组合布局,不。 什么是'背景图像或部分的颜色'?它是给定部分的单元格的背景颜色吗? 没有。您可以在部分本身 (NSCollectionLayoutSection
) 上使用装饰项来为 while 部分提供背景
面临类似问题。有人找到解决方案吗?
【参考方案1】:
经过一番努力,我想出了一个办法。它本身并不太 hacky,但需要额外的 hack 才能解决似乎是 UIKit 错误的问题。
注意事项
仅当您的部分内容和部分标题的高度都是绝对的并且提前知道时(至少在部分布局提供程序中),这才有效。
这对我来说很有效,因为我的标题和单元格的高度都是固定的,而且我每个部分只使用一排水平滚动的单元格。
背景视图不能水平滚动(假设是垂直滚动的集合视图。
在我的情况下,我希望固定部分背景图像,单元格在它们上方水平(正交)滚动。
约束/假设
我们只能使用组合布局(在我的例子中是为了获得简单的正交滚动)。
设置背景视图的工具(问题中提到)将不起作用,因为 它不能 通过补充视图注册或任何其他方式配置每个部分。 所以我们必须使用常规的补充项目。
补充项目必须在部分上以获得正确的尺寸,这 表示仅使用 NSCollectionLayoutBoundarySupplementaryItem。
3.1。虽然可以欺骗不同的类型(例如组上的非边界补充项目) 变成正确的大小和位置,使用技巧导致 UIKit 不 知道背景何时真正可见,这会导致闪烁 滚动时进/出。
尽管附加到章节,章节补充项目将是 垂直定位仅相对于单元格,忽略标题部分 部分。
更糟糕的是,这种对齐方式与将高度设置为总截面相结合 height 导致补充项拉伸该部分的高度 在单元格下方,使该部分太高。
有一个为补充项目设置位置偏移的工具, 但是由于我只能假设是一个错误(即使偏移量为 0), 使用它会导致节标题高度折叠为零,从而导致 下面的单元格向上移动并覆盖它。
解决方案
所以,为了解决所有这些问题,我所做的是:
-
将背景补充项大小设置为标题的已知高度+单元格/行+它们之间的任何间距。
通过垂直偏移将背景项目拉到标题下方
标题高度(使用偏移量会导致单元格向上移动;请参阅约束 6)。
通过将部分插图顶部填充高度
标头 (
hackInsets
)。
将背景的前/后边缘拉到视图/屏幕边缘,以
让它全出血(通常它会像内容一样插入)。我们这样做是通过
在背景中的背景图像视图上设置负边距
补充视图注册。
在背景视图上设置负 z-index 以将其保留在单元格和标题下方。
在代码中,相关部分如下所示:
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(Self.headerHeight))
let headerSupplementaryItem = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: ElementKind.header, alignment: .top)
let hackInsets = NSDirectionalEdgeInsets(top: Self.headerHeight, leading: 0, bottom: 0, trailing: 0)
let backgroundHeight = MySectionHeaderView.nominalSize.height + Self.interItemSpacing + MyCollectionViewCell.nominalSize.height
let backgroundOffset = CGPoint(x: 0, y: -MySectionHeaderView.nominalSize.height)
let backgroundAnchor = NSCollectionLayoutAnchor(edges: .top, absoluteOffset: backgroundOffset)
let backgroundSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(backgroundHeight))
let backgroundSupplementaryItem = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: backgroundSize, elementKind: ElementKind.background, containerAnchor: backgroundAnchor)
backgroundSupplementaryItem.zIndex = -1
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
section.contentInsets = Self.sectionInsets.summedWith(hackInsets)
section.boundarySupplementaryItems = [headerSupplementaryItem, backgroundSupplementaryItem]
【讨论】:
以上是关于如何使用组合布局为不同部分设置不同的背景?的主要内容,如果未能解决你的问题,请参考以下文章
Android如何实现同一个布局保证高度不变,使用不同高度的背景
GoogleServices - 如何使用flavorDimensions 为每种风味组合设置不同的applicationId?