Jetpack Compose - 将布局的子级扩展到边界之外

问题描述 投票:0回答:1

我正在寻找一种使布局元素(行或列)的子元素在垂直方向上延伸超出其父元素边界的方法。我想这样做是因为我想让背景中的行设置颜色,但子元素的周围区域是透明的。

这是我想要实现的目标的视觉表示:(想发布图像,但我还没有足够的声誉)

  -------
  |     | <- extended element
  |     |
--|     |----------
| |     |         | <- row with background
| -------         |
-------------------

理想情况下,该行的假设父级应该尊重扩展子级的高度。这是因为,据我了解,扩展部分通常会被其上方的其他组件或屏幕边缘切断(因为它超出了边界)。

我已经尝试了两件事

使用 onGloballyPositioned

使用此方法,可能可以通过某种方式实现,但我没有找到使用 LayoutCooperatives lambda 参数提供的位置方法来实现此目的的方法。

此外,我观察到子元素在第一次合成后“跳跃”位置。如果可能的话我想避免这种情况。

使用这个答案

中描述的方法

有了这个,我可以更改子元素的位置以及行本身,但调整大小似乎不起作用。

也许我在某个地方做错了什么,但这就是我现在得到的:

val itemWidth = 128
val itemHeight = 256

Row(
    modifier = Modifier.fillMaxWidth()
) {
    Box(
        modifier = Modifier
            .width(itemWidth.dp)
            .layout { measurable, constraints ->
                val placeable = measurable.measure(
                    constraints.copy(
                        maxHeight = itemHeight.dp.roundToPx()
                    )
                )
                layout(
                    placeable.width,
                    placeable.height
                ) {
                    placeable.place(0, 0)
                }
            }
            .background(color = Color.Blue)
        )
        Text(
            text = "This is text filling the rest of the row",
            modifier = Modifier
                .weight(1f)
                .padding(8.dp)
        )
    }
}
android layout android-jetpack-compose
1个回答
0
投票

约束是衡量可组合项作为可测量项的范围。如果未设置 minHieght,则它来自父级或先前的大小约束。如果它是 0,您的可组合项将在 256.dp 的 0 像素值之间进行测量,因此您需要将 minHeight 设置为与 maxHeight 相同的值。

同时设置 placeable.place(0, yPos) 和 yPos 低于 0 将使其位于 Row 中定义的位置之上。

最后,如果您不将高度分配给父行,它将获得具有最大高度的子行的高度,其中

Box
带有布局修饰符。

val itemWidth = 128
val itemHeight = 256

@Preview
@Composable
fun LayoutTest() {
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        Row(
            modifier = Modifier
                .padding(top = 300.dp)
                .fillMaxWidth()
                .height(50.dp)
                .border(2.dp, Color.Red)
        ) {
            Box(
                modifier = Modifier
                    .width(itemWidth.dp)
                    .layout { measurable, constraints ->
                        val placeable = measurable.measure(
                            constraints.copy(
                                minHeight = itemHeight.dp.roundToPx(),
                                maxHeight = itemHeight.dp.roundToPx()
                            )
                        )
                        layout(
                            placeable.width,
                            placeable.height
                        ) {
                            placeable.placeRelative(0, 0)
                        }
                    }
                    .background(color = Color.Blue)
                    .border(2.dp, Color.Green)

            )
            Text(
                text = "This is text filling the rest of the row",
                modifier = Modifier
                    .weight(1f)
                    .padding(8.dp)
            )
        }
    }
}

结果是这样的

enter image description here

蓝色框居中的原因是它不遵守父级约束,因为父级试图将其居中。您可以参考这个答案了解更多详细信息,但一般来说,如果测量不遵守父级或之前的修饰符约束,则无论它更大还是更小,它都是中心。

为了克服这个问题,你需要用

抵消两个差值
val userOffset = 0
placeable.placeRelative(
    x = 0,
    y = (constraints.maxHeight - placeable.height) / 2 + userOffset
)

将会有结果

enter image description here

如果为 userOffset 设置负值,蓝色框将放置在靠近顶部的位置。

© www.soinside.com 2019 - 2024. All rights reserved.