如何在Jetpack compose中使用xml:s android:id?

aurhwmvo  于 2022-12-09  发布在  Android
关注(0)|答案(1)|浏览(223)

如何像下面这样使用xml:s android:id

<TextView android:id="@id/randomId">

在Jetpack作曲?我在想这样的事情:

Text(modifier = Modifier.layoutId("randomId"), text = text)

我这样问是因为我使用Appium,它可以识别android:ids,我也想为Compose做同样的事情。

sgtfey8w

sgtfey8w1#

Jetpack Compose是一个声明性的UI,您可以使用@Composable注解创建具有函数的UI组件,这与View系统不同,在View系统中,您可以创建View或ViewGroup的示例,并使用您定义的ID获取它以设置属性。在Jetpack Compose中,您可以将Composable的属性声明为函数的参数。
Modifier.layoutId用于在使用特定布局构建自定义可合成对象时计算子可合成对象的尺寸和位置。

/**
 * Retrieves the tag associated to a composable with the [Modifier.layoutId] modifier.
 * For a parent data value to be returned by this property when not using the [Modifier.layoutId]
 * modifier, the parent data value should implement the [LayoutIdParentData] interface.
 *
 * Example usage:
 * @sample androidx.compose.ui.samples.LayoutTagChildrenUsage
 */
val Measurable.layoutId: Any?
    get() = (parentData as? LayoutIdParentData)?.layoutId

当你构建一个自定义布局时,总的来说

@Composable
private fun MyLayout(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {

    Layout(
        modifier = modifier,
        content = content
    ) { measurables: List<Measurable>, constraints: Constraints ->

        val placeables: List<Placeable> = measurables.map { measurable: Measurable ->
            measurable.measure(constraints)
        }

        // Width and height of parent composable depends on requirements
        layout(constraints.maxWidth, constraints.maxHeight) {
            placeables.forEach { placeable: Placeable ->
                // place composables based on requirements vertically, horizontally, diagonal, etc.
            }
        }
    }
}

1-您创建一个布局,该布局需要使用lambda设置的MeasurePolicy,并通过layout(width, height)函数返回MeasureResult。
2-约束是由大小修饰符、滚动修饰符或父级选择限制大小的方式设置的限制。In Constraints section i解释了哪个修饰符返回哪个界限。您只能在这些界限内测量可测量值。
但是,如果您不想通过constraints.copy()Constraints.fixed()constraints.offset()选择不同的边界,您可以修改约束。最大边界仍然是父级的最大边界。
然后,您只测量一次可测量值,如果您尝试再次测量,则会得到异常
然而,有时候你需要根据另一个可组合组件来设置可组合组件的维度。例如,如果Image是100.dp,这是在运行时设置的,而你想将Text调整为100.dp,但你不知道ImageText在内容中的设置顺序。
您需要使用SubcomposeLayout(它使用子合成函数来重新测量合成对象),或者您可以使用Modifier.layoutId来确定您首先测量哪个合成对象,如下例所示,或者如本答案的“选择性测量以将一个同级对象与另一个同级对象匹配”部分所示

@Composable
private fun MyLayout(
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit
) {

    Layout(
        modifier = modifier,
        content = content
    ) { measurables: List<Measurable>, constraints: Constraints ->

        val imageMeasurable: Measurable = measurables.find { it.layoutId == "image" }!!
        val textMeasurable: Measurable = measurables.find { it.layoutId == "text" }!!

        val imagePlaceable = imageMeasurable.measure(constraints.copy(minWidth = 0, minHeight = 0))

        // Limit text width to image width by setting min and max width at image width
        val textPlaceable = textMeasurable.measure(
            constraints.copy(
                minWidth = imagePlaceable.width,
                maxWidth = imagePlaceable.width
            )
        )

        val width = imagePlaceable.width
        val imagePlaceableHeight = imagePlaceable.height
        val height = imagePlaceableHeight + textPlaceable.height
        // Width and height of parent composable depends on requirements
        layout(width, height) {
            imagePlaceable.placeRelative(0, 0)
            textPlaceable.placeRelative(0, imagePlaceableHeight)
        }
    }
}

演示

MyLayout(
    modifier = Modifier
        .fillMaxWidth()
        .border(1.dp, Color.Cyan)
) {
    Image(
        modifier = Modifier
            .size(150.dp)
            .layoutId("image"),
        painter = painterResource(id = R.drawable.landscape1),
        contentDescription = null,
        contentScale = ContentScale.FillBounds
    )

    Text(
        modifier = Modifier
            .layoutId("text")
            .border(2.dp, Color.Red),
        text = "Hello world some very long text that will be scaled"
    )
}

MyLayout(
    modifier = Modifier
        .fillMaxWidth()
        .border(1.dp, Color.Cyan)
) {

    Text(
        modifier = Modifier
            .layoutId("text")
            .border(2.dp, Color.Red),
        text = "Hello world some very long text that will be scaled"
    )

    Image(
        modifier = Modifier
            .size(100.dp)
            .layoutId("image"),
        painter = painterResource(id = R.drawable.landscape1),
        contentDescription = null,
        contentScale = ContentScale.FillBounds
    )

}

测试结果

如图所示,我们首先使用layoutId获取Image,然后测量Text,使其宽度与Image匹配。我认为这不适用于appium,除非它有某种针对Modifier的检查器

相关问题