自定义布局 Android 组成可测量的宽度
Custom Layout Android Compose measurable width
我正在尝试在 Android 中实现自定义“行”布局,如下所示:
@Composable
fun CustomLayout(modifier: Modifier, content: @Composable () -> Unit){
Layout(
modifier = modifier,
content = content,
) { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
var xPos = 0
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { placeable ->
placeable.placeRelative(x = xPos, y = 0)
xPos += placeable.width
}
}
}
}
这是此可组合项的预览:
@Preview(name = "Preview")
@Composable
fun customLayoutPreview() {
CustomLayout(Modifier.size(1080.dp,100.dp)){
Box(
Modifier
.size(32.dp, 64.dp)
.background(Color.Red)) {
}
Box(
Modifier
.size(100.dp, 64.dp)
.background(Color.Green)) {
}
Box(
Modifier
.size(32.dp, 64.dp)
.background(Color.Yellow)) {
}
}
}
这里的问题是每个 measurable
(盒子)在测量后得到 parent 宽度,因此是 1080dp,而不是传递给盒子的所需宽度,这导致第一个 child 取全部 space.
见:
Preview
理论上的预期是什么:
(方框 32dp)(方框 100dp)(方框 32dp)
我在这里缺少什么?
我尝试了文档,但我无法理解如何实现像普通 android 自定义 ViewGroup.onMeasure
这样的东西:
view.measure(MeasureSpec.makeMeasureSpec(wantedSize, AT_MOST or EXACT))
,其中 wantedSize
可以从 LayoutParams 或 WRAP_CONTENT
策略中获取。
环境:
Android 北极狐工作室。
撰写:1.0.0。
科特林:1.5.10。
AGP 和 Gradle:7.0.0.
好的,你不应该在那边使用 placeable.measuredWidth
。只需将其替换为 placeable.width
。此外,在您的映射逻辑中,您根本不需要 val
。就这样做
val placeables = measurables.map {
it.measure(constraints)
}
访问此处了解详情
您必须复制您的约束并将最小值更改为 0。像这样更改它:
@Composable
fun CustomLayout(modifier: Modifier, content: @Composable () -> Unit) {
Layout(
modifier = modifier,
content = content,
) { measurables, constraints ->
// MAKE A COPY WITH 0 FOR MIN
val looseConstraints = constraints.copy(
minWidth = 0,
minHeight = 0
)
val placeables = measurables.map { measurable ->
measurable.measure(looseConstraints)
}
var xPos = 0
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { placeable ->
placeable.placeRelative(x = xPos, y = 0)
xPos += placeable.width
}
}
}
}
我正在尝试在 Android 中实现自定义“行”布局,如下所示:
@Composable
fun CustomLayout(modifier: Modifier, content: @Composable () -> Unit){
Layout(
modifier = modifier,
content = content,
) { measurables, constraints ->
val placeables = measurables.map { measurable ->
measurable.measure(constraints)
}
var xPos = 0
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { placeable ->
placeable.placeRelative(x = xPos, y = 0)
xPos += placeable.width
}
}
}
}
这是此可组合项的预览:
@Preview(name = "Preview")
@Composable
fun customLayoutPreview() {
CustomLayout(Modifier.size(1080.dp,100.dp)){
Box(
Modifier
.size(32.dp, 64.dp)
.background(Color.Red)) {
}
Box(
Modifier
.size(100.dp, 64.dp)
.background(Color.Green)) {
}
Box(
Modifier
.size(32.dp, 64.dp)
.background(Color.Yellow)) {
}
}
}
这里的问题是每个 measurable
(盒子)在测量后得到 parent 宽度,因此是 1080dp,而不是传递给盒子的所需宽度,这导致第一个 child 取全部 space.
见: Preview
理论上的预期是什么: (方框 32dp)(方框 100dp)(方框 32dp)
我在这里缺少什么?
我尝试了文档,但我无法理解如何实现像普通 android 自定义 ViewGroup.onMeasure
这样的东西:
view.measure(MeasureSpec.makeMeasureSpec(wantedSize, AT_MOST or EXACT))
,其中 wantedSize
可以从 LayoutParams 或 WRAP_CONTENT
策略中获取。
环境: Android 北极狐工作室。 撰写:1.0.0。 科特林:1.5.10。 AGP 和 Gradle:7.0.0.
好的,你不应该在那边使用 placeable.measuredWidth
。只需将其替换为 placeable.width
。此外,在您的映射逻辑中,您根本不需要 val
。就这样做
val placeables = measurables.map {
it.measure(constraints)
}
访问此处了解详情
您必须复制您的约束并将最小值更改为 0。像这样更改它:
@Composable
fun CustomLayout(modifier: Modifier, content: @Composable () -> Unit) {
Layout(
modifier = modifier,
content = content,
) { measurables, constraints ->
// MAKE A COPY WITH 0 FOR MIN
val looseConstraints = constraints.copy(
minWidth = 0,
minHeight = 0
)
val placeables = measurables.map { measurable ->
measurable.measure(looseConstraints)
}
var xPos = 0
layout(constraints.maxWidth, constraints.maxHeight) {
placeables.forEach { placeable ->
placeable.placeRelative(x = xPos, y = 0)
xPos += placeable.width
}
}
}
}