Jetpack Compose - 布局可重复使用的组件
2022-11-02
779
为了练习使用 Jetpack Compose 中的可重用组件,我开始了一个小练习。 见下图。
我想象绿色行、输入行和它们之间的行具有相同的结构。 第一个元素获得可用空间,第二个元素占用 50.dp,最后一个元素占用 70.dp。 我尝试将宽度分成变量,并将这些变量作为修饰符传递给行中的单个元素。我认为如果我需要额外的字段,我可以毫无问题地扩展它。
代码不起作用!
@Composable
fun groundComponent(
modifier: Modifier = Modifier,
spaceBetween: Dp = 0.dp,
color: Color,
content: @Composable () -> Unit
) {
Surface(
color = color
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(spaceBetween)
) {
content()
}
}
}
@Composable
fun inputSection() {
val firstRowWidth = 1F
val secondRowWidth = 70.dp
val thirdRowWidth = 50.dp
Text("Add Ingredient")
groundComponent(color = Color.Green){
Text( text="Ingredient", modifier = Modifier.weight(firstRowWidth ))
Text( text="Amount", modifier = Modifier.widthIn(secondRowWidth ))
Text( text="Unit", modifier = Modifier.widthIn(thirdRowWidth ))
}
groundComponent{
Text( text="Sugar", modifier = Modifier.weight(firstRowWidth ))
Text( text="500", modifier = Modifier.widthIn(secondRowWidth ))
Text( text="gr", modifier = Modifier.widthIn(thirdRowWidth ))
}
groundComponent{
Text( text="Carrot", modifier = Modifier.weight(firstRowWidth ))
Text( text="1.5", modifier = Modifier.widthIn(secondRowWidth ))
Text( text="kg", modifier = Modifier.widthIn(thirdRowWidth ))
}
groundComponent{
TextField(
value = "newIngredient",
onValueChange = {},
modifier = Modifier.weight(firstRowWidth ))
TextField(
value = "newAmount",
onValueChange = {},
modifier = Modifier.widthIn(secondRowWidth )
)
TextField(
value = "newUnit",
onValueChange = {},
modifier = Modifier.widthIn(thirdRowWidth )
)
}
Button(onClick={}){Text("add")}
}
我在使用 .weight 修饰符时遇到了几个错误。 那么解决这种情况的正确方法是什么呢?
谢谢!
2个回答
Modifier.weight 是在特定范围(例如 RowScope 和 ColumnScope)中定义的修饰符。要使用在特定范围中定义的修饰符,您需要将 Receiver 添加到内容中。BoxScope 定义为 Modifier.align(),例如,您也可以定义您的范围。
@Composable
fun GroundComponent(
modifier: Modifier = Modifier,
spaceBetween: Dp = 0.dp,
color: Color=Color.Unspecified,
content: @Composable RowScope.() -> Unit
) {
Surface(
color = color
) {
// Can't call content here because it has RowScope as receiver
// content()
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(spaceBetween)
) {
content()
}
}
}
此外,在 InputSection 中,您将权重分数定义为
val firstRowWidth = 1F
val secondRowWidth = 70.dp
val thirdRowWidth = 50.dp
这些值应该彼此成比例
例如,如果您设置 1/5/6。或者在 0f-1f 之间
并且按照惯例,您可以使用大写首字母命名 Composable,因为它们被视为小部件。
Thracian
2022-11-02
感谢您的回复和相当不错的解释! 在您的帮助下,我以这种方式解决了我的问题。
@Composable
fun InputRowGroundComponent(
modifier: Modifier = Modifier,
spaceBetweenElements: Dp = 0.dp,
color: Color,
content: @Composable RowScope.() -> Unit
) {
Surface(
color = color
) {
Row(
modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(spaceBetweenElements),
verticalAlignment = Alignment.CenterVertically
) {
content()
}
}
}
@Composable
fun OverviewHeader(
modifier: Modifier = Modifier,
text: String
) {
Text(
modifier = modifier,
text = text,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Center
)
}
@Composable
fun OverviewContent(
modifier: Modifier = Modifier,
text: String
) {
Text(
modifier = modifier,
text = text,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
)
}
@Preview(showBackground = true, widthDp = 460)
@Composable
fun testPrev() {
val rowWeights = listOf(6F,3F,2F)
val rowSpacing = 8.dp
val indentation = 10.dp
Column(
modifier = Modifier.padding(8.dp),
verticalArrangement = Arrangement.spacedBy(rowSpacing)
) {
InputRowGroundComponent(
modifier = Modifier.heightIn(45.dp),
spaceBetweenElements = rowSpacing,
color = Color.Green
) {
OverviewHeader(text = "Ingredient", modifier = Modifier.weight(rowWeights[0]))
OverviewHeader(text = "Amount", modifier = Modifier.weight(rowWeights[1]))
OverviewHeader(text = "Unit", modifier = Modifier.weight(rowWeights[2]))
}
InputRowGroundComponent(
modifier = Modifier.heightIn(30.dp),
spaceBetweenElements = rowSpacing,
color = Color.Unspecified
) {
OverviewContent(text = "Sugar", modifier = Modifier.weight(rowWeights[0]).padding(start=indentation))
OverviewContent(text = "500", modifier = Modifier.weight(rowWeights[1]).padding(start=indentation))
OverviewContent(text = "gr", modifier = Modifier.weight(rowWeights[2]).padding(start=indentation))
}
InputRowGroundComponent(
modifier = Modifier.heightIn(30.dp),
spaceBetweenElements = rowSpacing,
color = Color.Unspecified
) {
OverviewContent(text = "Carrot", modifier = Modifier.weight(rowWeights[0]).padding(start=indentation))
OverviewContent(text = "1.5", modifier = Modifier.weight(rowWeights[1]).padding(start=indentation))
OverviewContent(text = "kg", modifier = Modifier.weight(rowWeights[2]).padding(start=indentation))
}
InputRowGroundComponent(
spaceBetweenElements = rowSpacing,
color = Color.Unspecified
) {
TextField(value = "", onValueChange = {}, modifier = Modifier.weight(rowWeights[0]))
TextField(value = "", onValueChange = {}, modifier = Modifier.weight(rowWeights[1]))
TextField(value = "", onValueChange = {}, modifier = Modifier.weight(rowWeights[2]))
}
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { /*Todo*/ },
content = {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "Add Ingredient"
)
Text(
text = "Add"
)
}
}
)
}
}
这种方法现在正确吗?
Pferdesalbe
2022-11-06