android - Jetpack Compose SubcomposeLayout 是如何工作的?

标签 android android-jetpack-compose

可以在 official documents 中看到有一个名为 SubcomposeLayout 的布局定义为

Analogue of Layout which allows to subcompose the actual content during the measuring stage for example to use the values calculated during the measurement as params for the composition of the children.

Possible use cases:

You need to know the constraints passed by the parent during the composition and can't solve your use case with just custom Layout or LayoutModifier. See androidx.compose.foundation.layout.BoxWithConstraints.

You want to use the size of one child during the composition of the second child.

You want to compose your items lazily based on the available size. For example you have a list of 100 items and instead of composing all of them you only compose the ones which are currently visible(say 5 of them) and compose next items when the component is scrolled.


我用 SubcomposeLayout 搜索了 Stackoverflow关键字,但找不到任何相关信息,创建了这个示例代码,从官方文档中复制了大部分内容,以测试和学习它是如何工作的
@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 的描述功能

    Performs subcomposition of the provided content with given slotId. Params: slotId - unique id which represents the slot we are composing into. If you have fixed amount or slots you can use enums as slot ids, or if you have a list of items maybe an index in the list or some other unique key can work. To be able to correctly match the content between remeasures you should provide the object which is equals to the one you used during the previous measuring. content - the composable content which defines the slot. It could emit multiple layouts, in this case the returned list of Measurables will have multiple elements.


    有人可以解释它的含义或/并为 SubcomposeLayout 提供工作样本吗? ?

    最佳答案

    It's supposed to re-measure a component based on another component size...

    SubcomposeLayout不重新测量。它允许推迟内容的组成和测量,直到其父项的约束已知并且可以测量其内容,从中可以将结果作为参数传递给延迟的内容。上面的例子计算了mainContent生成的内容的最大尺寸。并将其作为参数传递给 deferredContent .然后测量 deferredContent并放置mainContentdeferredContent在彼此之上。
    最简单的使用示例SubcomposeLayoutBoxWithConstraints它只是将它从父级接收到的约束直接传递给它的内容。在布局期间出现的父级测量框的 sibling 之前,框的约束是未知的,因此 content 的组成被推迟到布局。
    同样,对于上面的示例,maxSizemainContent直到布局才知道deferredContent在布局中调用一次 maxSize是计算出来的。它总是放置 deferredContentmainContent 之上所以假设 deferredContent使用 maxSize以某种方式避免掩盖 mainContent 生成的内容.可能不是可组合的最佳设计,但可组合的目的是说明性的,本身没有用处。
    请注意 subcompose可以在 layout 中多次调用堵塞。例如,LazyRow 中发生的情况。 . slotId允许 SubcomposeLayout跟踪和管理通过调用 subcompose 创建的乐曲.例如,如果您从一个数组生成内容,您可能希望使用数组的索引作为它的slotId。允许 SubcomposeLayout确定哪个subcompose上次生成的应该在重组期间使用。此外,如果 slotid不再使用,SubcomposeLayout将处置其相应的成分。
    至于在哪里slotId去,这取决于 SubcomposeLayout 的调用者.如果内容需要它,请将其作为参数传递。上面的例子不需要它作为 slotId deferredContent 总是相同的所以它不需要去任何地方。

    关于android - Jetpack Compose SubcomposeLayout 是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69663194/

    相关文章:

    java - System.err﹕javax.net.ssl.SSLPeerUnverifiedException : No peer certificate

    android - 使用 CursorLoader 和 FilterQueryProvider 过滤 ListView?

    android - Jetpack Compose Focus Order with Talkback

    android - Jetpack Compose - 每次单击按钮都不起作用

    android - Jetpack 撰写 : react to Slider changed value

    java - 根据条形的宽度为其着色

    android - 在没有 SearchView 的情况下启动默认搜索 Activity

    java - Gson在JAVA Android中将 boolean 值从1反序列化为false

    android - E/GlanceAppWidget : Error in Glance App Widget IllegalStateException: CompositionLocal LocalConfiguration not present

    Android Jetpack compose 如何测试背景颜色