android - Jetpack Compose SubcomposeLayout 是如何工作的?
问题描述
从官方文档中可以看出,有一个名为 SubcomposeLayout 的布局定义为
布局的模拟,允许在测量阶段对实际内容进行子组合,例如使用测量期间计算的值作为子项组合的参数。
可能的用例:
您需要知道父级在组合过程中传递的约束,并且不能仅使用自定义 Layout 或 LayoutModifier 来解决您的用例。请参阅 androidx.compose.foundation.layout.BoxWithConstraints。
您想在第二个孩子的构图中使用一个孩子的大小。
您想根据可用大小懒惰地组合您的项目。例如,您有一个包含 100 个项目的列表,而不是编写所有项目,您只编写当前可见的项目(比如其中 5 个)并在组件滚动时编写下一个项目。
我用关键字搜索了 StackoverflowSubcomposeLayout
但找不到任何关于它的信息,创建了这个示例代码,从官方文档中复制了大部分内容,以测试并了解它是如何工作的
@Composable
private fun SampleContent() {
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
SubComponent(
mainContent = {
Text(
"MainContent",
modifier = Modifier
.background(Color(0xffF44336))
.height(60.dp),
color = Color.White
)
},
dependentContent = {
val size = it
println(" Dependent size: $size")
Column() {
Text(
"Dependent Content",
modifier = Modifier
.background(Color(0xff9C27B0)),
color = Color.White
)
}
}
)
}
}
@Composable
private fun SubComponent(
mainContent: @Composable () -> Unit,
dependentContent: @Composable (IntSize) -> Unit
) {
SubcomposeLayout { constraints ->
val mainPlaceables = subcompose(SlotsEnum.Main, mainContent).map {
it.measure(constraints)
}
val maxSize = mainPlaceables.fold(IntSize.Zero) { currentMax, placeable ->
IntSize(
width = maxOf(currentMax.width, placeable.width),
height = maxOf(currentMax.height, placeable.height)
)
}
layout(maxSize.width, maxSize.height) {
mainPlaceables.forEach { it.placeRelative(0, 0) }
subcompose(SlotsEnum.Dependent) {
dependentContent(maxSize)
}.forEach {
it.measure(constraints).placeRelative(0, 0)
}
}
}
}
enum class SlotsEnum { Main, Dependent }
它应该根据另一个组件的大小重新测量一个组件,但这段代码的实际作用对我来说是个谜。
- 函数是如何
subcompose
工作的? - 有什么意义,
slotId
我们可以通过某种方式获得 slotId 吗?
subCompose
功能说明
使用给定的 slotId 执行提供的内容的子组合。参数: slotId - 代表我们正在组合的插槽的唯一 ID。如果您有固定数量或插槽,则可以使用枚举作为插槽 id,或者如果您有项目列表,则列表中的索引或其他一些唯一键可以工作。为了能够在重新测量之间正确匹配内容,您应该提供与您在上次测量期间使用的对象相同的对象。content - 定义插槽的可组合内容。它可以发出多个布局,在这种情况下,返回的 Measurables 列表将具有多个元素。
有人可以解释它的含义或/并提供一个工作样本SubcomposeLayout
吗?
解决方案
它应该根据另一个组件尺寸重新测量一个组件...
SubcomposeLayout
不重新测量。它允许推迟内容的组成和测量,直到其父项的约束已知并且可以测量其内容,从中可以将结果作为参数传递给延迟的内容。上面的例子计算生成的内容的最大大小,mainContent
并将其作为参数传递给deferredContent
. 然后,它测量deferredContent
并将两者mainContent
放在deferredContent
一起。
最简单的使用示例SubcomposeLayout
是 BoxWithConstraints,它只是将其从父级接收到的约束直接传递给其内容。在布局期间发生的父级测量框的兄弟姐妹之前,框的约束是未知的,因此组合content
被推迟到布局。
类似地,对于上面的示例,直到 layout 才知道 of,所以maxSize
在layout once被计算时调用。它总是放在最上面,因此假定它以某种方式使用以避免模糊由. 可能不是可组合的最佳设计,但可组合的目的是说明性的,本身没有用处。mainContent
deferredContent
maxSize
deferredContent
mainContent
deferredContent
maxSize
mainContent
请注意,subcompose
可以在块中多次调用layout
。例如,这是发生在LazyRow
. slotId
允许SubcomposeLayout
跟踪和管理调用创建的作品subcompose
。例如,如果您从一个数组生成内容,您可能希望使用数组的索引作为它slotId
允许SubcomposeLayout
确定subcompose
在重组期间应该使用上次生成的内容。此外,如果 aslotid
不再使用,SubcomposeLayout
将处理其相应的组合。
至于去哪里slotId
,这取决于调用者SubcomposeLayout
。如果内容需要它,请将其作为参数传递。上面的例子不需要它,因为slotId
它总是一样的,deferredContent
所以它不需要去任何地方。
推荐阅读
- python - 如何将数据框字典转换为数据框?
- node.js - 摩卡说测试成功,但它抛出了一个异常
- javascript - nodejs lstat 找不到文件
- command-line - 如何通过命令行从注册表项值中获取数据
- python - 重新索引 DataFrame 并合并两列
- apache-kafka - kafka和zookepeer高可用配置
- haskell - 从没有模式匹配的 JSON 值字符串文本中提取文本
- node.js - NodeMailer Parser - 将解析的内容转换为文件
- php - 未定义变量:allUsersData(查看:C:\xampp\htdocs\plearning\resources\
- file - 找不到文件 - 通过 CMD 使用 e:\ 命令运行位于闪存驱动器上的文件