【发布时间】:2022-07-18 16:01:49
【问题描述】:
我想在测量可测量对象并使用布局功能放置可放置对象后动态设置androidx.compose.foundation.Canvas 大小,但 Canvas 需要具有特定大小的修饰符,如何使用 Layout 和 Canvas 以有效的方式实现这一点。
我想要实现的是在图像中设置内容并添加一些空间和绘制 红色区域中的箭头用于创建对话气泡,如图here。
图像中的第一个容器是正确的,其中 Modifier.layout 和 Modifier.drawbackground 为
@Composable
private fun MyComposable(modifier: Modifier = Modifier) {
Row(
modifier = Modifier
) {
var totalSize = Size.Zero
val layoutModifier = modifier
.layout { measurable, constraints ->
val placeable = measurable.measure(constraints)
totalSize = Size(placeable.width + 50f, placeable.height.toFloat())
println("MyComposable() LAYOUT placeable: $placeable")
layout(totalSize.width.roundToInt(), placeable.height) {
placeable.place(0, 0)
}
}
.drawBehind {
println("MyComposable() drawBehind size: $size")
drawRect(Color.Red, size = totalSize, style = Stroke(2f))
drawRect(Color.Blue, size = size, style = Stroke(2f))
}
Column(modifier = layoutModifier) {
Text("First Text")
Text("Second Text")
}
}
}
还有日志
I: MyComposable() LAYOUT placeable width: 250, height: 124
I: MyComposable() drawBehind size: Size(250.0, 124.0)
带有布局和画布
@Composable
private fun CanvasLayout(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
var widthInDp by remember { mutableStateOf(0.dp) }
var heightInDp by remember { mutableStateOf(0.dp) }
Layout(content = content, modifier = modifier) { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
val maxWidth = placeables.maxOf { it.width } + 50
val height = placeables.sumOf { it.height }
widthInDp = (maxWidth / density).toDp()
heightInDp = (height / density).toDp()
println("???? CanvasLayout() LAYOUT maxWidth: $maxWidth, height: $height placeables: ${placeables.size}")
var yPos = 0
layout(maxWidth, height) {
placeables.forEach { placeable: Placeable ->
placeable.placeRelative(0, yPos)
yPos += placeable.height
}
}
}
androidx.compose.foundation.Canvas(
modifier = Modifier.size(widthInDp, heightInDp),
onDraw = {
println("???? CanvasLayout() CANVAS size: $size")
drawRect(Color.Blue, size = size, style = Stroke(2f))
}
)
}
如图所示,底部矩形绘制在文本组合下方而不是围绕它们并调用layout 两次
I: ???? CanvasLayout() LAYOUT maxWidth: 300, height: 124 placeables: 2
I: ???? CanvasLayout() CANVAS size: Size(0.0, 0.0)
I: ???? CanvasLayout() LAYOUT maxWidth: 300, height: 124 placeables: 2
I: ???? CanvasLayout() CANVAS size: Size(114.0, 47.0)
Layout和Canvas一起使用的正确和高效方法是什么?
【问题讨论】:
-
第一个例子有什么问题?对于第二个,您似乎在
Column中调用它,所以这是预期的结果。在Canvas的源代码中可以看到,它只在修饰符上调用drawBehind,所以你也可以直接调用它。 -
没有错。我只想拥有自己的
Layout,而不是添加Column来包装其他将在实际实现中的组合。是的,你是对的,因为外部可组合是 Column,它位于Canvas下方Layout之下。所以我使用了Layout和Modifier.drawBehind并放弃了Canvas。 -
正如你所说,我检查了
Canvas源代码,正如你所说,它只不过是Spacer(modifier.drawBehind(onDraw))。我以为是Layout和其他属性。也许我应该检查以imageBitmap作为参数的androidx.compose.ui.graphics.Canvas。
标签: android android-jetpack-compose android-jetpack-compose-canvas