如何使用组合布局为不同部分设置不同的背景?

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?

如何在一列中为不同的组合框设置不同的商店?

如何使用 QSS 为禁用的按钮设置不同的背景颜色?

如何使用swift在iOS中为活动设置两种不同大小的背景图像作为横向和纵向模式

如何在 cakephp 中为不同的模型设置不同的布局