我在Compose中有一个“简单”的布局,在Column
中有两个元素:
- 顶部图像
- 下面有4个方格,每个方格包含一些文本
我希望布局具有以下行为:
- 设置图像的最大高度为
screenWidth
- 设置图像的最小高度为
200.dp
- 图像应始终在一个正方形容器中(图像的裁剪很好)
- 让网格根据需要“增长”,以包围内容,使图像根据需要收缩
这意味着如果方块中的文本很短,图像将覆盖顶部的一个大方块。但如果任何一个方形文本真的很长,我希望整个网格按比例放大并缩小图像。以下是理想的结果:
1.当文本足够短时
x1c 0d1x的数据
1.当一段文字很长的时候
的
我已经在Compose中用ConstraintLayout
尝试过了,但是我不能正确地缩放方块。
使用Column
,我无法获得随大内容增长的选项-文本只是被截断,图像仍然是一个巨大的正方形。
这些是我构建的组件:
// the screen
Column {
Box(modifier = Modifier
.heightIn(min = 200.dp, max = screenWidth)
.aspectRatio(1f)
.border(BorderStroke(1.dp, Color.Green))
.align(Alignment.CenterHorizontally),
) {
Image(
painter = painterResource(id = R.drawable.puppy),
contentDescription = null,
contentScale = ContentScale.Crop
)
}
OptionsGrid(choicesList, modifier = Modifier.heightIn(max = screenHeight - 200.dp))
}
@Composable
fun OptionsGrid(choicesList: List<List<String>>, modifier: Modifier = Modifier) {
Column(
modifier = modifier
.border(1.dp, Color.Blue)
.padding(top = 4.dp, bottom = 4.dp)
.fillMaxHeight(),
verticalArrangement = Arrangement.Center
) {
choicesList.forEach { choicesPair ->
Row(modifier = Modifier.weight(0.5f)) {
choicesPair.forEach { choice ->
Box(
modifier = Modifier
.padding(4.dp)
.background(Color.White)
.weight(0.5f)
) {
Option(choice = choice)
}
}
}
}
}
}
@Composable
fun Option(choice: String) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Yellow)
.border(BorderStroke(1.dp, Color.Red)),
contentAlignment = Alignment.Center
) {
Text(
text = choice,
modifier = Modifier.padding(8.dp),
textAlign = TextAlign.Center,
)
}
}
字符串
我需要为此定制布局吗?我想这里发生的事情是,Column
首先测量图像,让它成为它的最大高度,因为屏幕上有空间,然后在测量网格时,它给它剩余的空间,仅此而已。
所以我需要一个从底部开始测量的布局?
2条答案
按热度按时间rmbxnbpk1#
以下是如何在不使用自定义布局的情况下完成此操作。
1.您需要在
OptionsGrid
之后计算图像大小。在这种情况下,可以使用Modifier.weight(1f, fill = false)
:它强制所有没有Modifier.weight
的视图被布置在任何加权元素之前。Modifier.weight
将覆盖您的Modifier.heightIn
,但我们可以从另一端限制其大小:在OptionsGrid
上使用Modifier.layout
。使用此修改器,我们可以覆盖应用于视图的约束。p.s.
Modifier.heightIn(max = screenWidth)
是多余的,因为视图无论如何都不会增长超过屏幕大小,除非宽度约束被覆盖,例如,使用滚动视图。.height(IntrinsicSize.Min)
将阻止OptionsGrid
超出所需的增长。请注意,is应该放在Modifier.layout
之后,因为它会将高度限制设为无穷大。请参阅why modifiers order matters。字符串
测试结果:
的数据
k10s72fa2#
我想这里发生的事情是,柱子首先测量图像,让它成为它的最大高度,因为屏幕上有空间,然后当测量网格时,它给它剩余的空间,仅此而已。
这是正确的,它沿着UI树向下,测量列的第一个子级(具有图像的框),并且由于图像没有任何子级,因此它将其大小返回给父级
Column
。(参见documentation)我很确定这需要一个自定义布局,所以这是我想到的:
首先,为了测试的目的,修改了一些可组合项(调整了一些修饰符,并将
Texts
替换为TextFields
,以便能够看到UI的React)字符串
现在,自定义布局
由于
subcompose
需要一个slotId
,而您只需要图像和网格的ID,因此您可以创建一个具有两个ID的Enum类。型
slotID:一个唯一的id,它代表我们正在合成的插槽。如果你有固定的数量或插槽,你可以使用枚举作为插槽ID,或者如果你有一个项目列表,也许列表中的索引或其他一些唯一的键可以工作。为了能够正确匹配两次重新测量之间的内容,您应该提供与上次测量期间使用的对象相同的对象。内容-定义插槽的可组合内容。它可以发出多个布局,在这种情况下,返回的Measurables列表将具有多个元素。
然后,用这个Composable,它接收一个屏幕宽度、高度、一个可选的修饰符和图像,以及网格
型
您可以测量网格的总高度,并使用它来计算图像的高度(当缩放到200 dp以下时,仍然没有管理到适当的UI,但应该不难)。
型
然后,将约束应用于图像,最后放置项目。
型
最后,调用前面的可组合函数
DynamicColumn
:型
PS:可能会更新这个明天,如果我能解决最小宽度的问题