如何在Jetpack Compose中将行底对齐?

30

我有一个带有一些行的列,我想将最后一行对齐到底部,但是这一行永远不会位于屏幕底部,它会紧接在前一行之后:

    Column {
        // RED BOX
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .height(130.dp)                
                .padding(vertical = 15.dp, horizontal = 30.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Column {
                Text(
                    text = stringResource(id = R.string.app_name),
                    style = TextStyle(fontSize = 40.sp),
                    color = Color.White
                )
                Text(
                    text = stringResource(id = R.string.app_description),
                    style = TextStyle(fontSize = 13.sp),
                    fontWeight = FontWeight.Bold,
                    color = Color.Black
                )
            }
        }

        Spacer(
            modifier = Modifier
                .fillMaxWidth()
                .height(15.dp)
        )

        // GREEN BOX
        val currentRoute = currentRoute(navController)
        items.forEach { item ->
            DrawerItem(item = item, selected = currentRoute == item.route) {
                navController.navigate(item.route) {
                    launchSingleTop = true
                }

                scope.launch {
                    scaffoldState.drawerState.close()
                }
            }
        }

        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 15.dp, horizontal = 30.dp),
            verticalAlignment = Alignment.Bottom,
            horizontalArrangement = Arrangement.Center
        ) {
            Text(
                text = BuildConfig.VERSION_NAME,
                style = TextStyle(fontSize = 11.sp),
                color = Color.Black,
            )
        }
    }

我想要得到与图片中显示的相同效果。我想要有第一行(红色),然后是第二行(绿色),最后在屏幕底部适合的第三行(蓝色)。

enter image description here

4个回答

35

您可以在绿盒子和蓝盒子之间使用 Spacer(modifier.weight(1f)) 创建间距,或者使用 Layout 函数创建自定义列,并将最后一个 Placeable 的 y 位置设置为 Composable 的高度减去最后一个 Composble 的高度。

    Column(modifier = Modifier
        .fillMaxHeight()
        .background(Color.LightGray)) {
        Text(
            "First Text",
            modifier = Modifier
                .background(Color(0xffF44336)),
            color = Color.White
        )
        Text(
            "Second Text",
            modifier = Modifier
                .background(Color(0xff9C27B0)),
            color = Color.White
        )
        Spacer(modifier = Modifier.weight(1f))
        Text(
            "Third Text",
            modifier = Modifier
                .background(Color(0xff2196F3)),
            color = Color.White
        )
    }

结果:

这里输入图片描述

自定义布局

@Composable
private fun CustomColumn(
    modifier: Modifier,
    content: @Composable () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->

        val looseConstraints = constraints.copy(
            minWidth = 0,
            maxWidth = constraints.maxWidth,
            minHeight = 0,
            maxHeight = constraints.maxHeight
        )

        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each child
            measurable.measure(looseConstraints)
        }

        // Track the y co-ord we have placed children up to
        var yPosition = 0


        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Place children in the parent layout
            placeables.forEachIndexed { index, placeable ->

                println("Placeable width: ${placeable.width}, measuredWidth: ${placeable.measuredWidth}")
                // Position item on the screen
                if (index == placeables.size - 1) {
                    placeable.placeRelative(x = 0, y = constraints.maxHeight - placeable.height)
                } else {
                    placeable.placeRelative(x = 0, y = yPosition)
                }

                // Record the y co-ord placed up to
                yPosition += placeable.height
            }
        }
    }
}

使用方法

    CustomColumn(
        modifier = Modifier
            .fillMaxHeight()
            .background(Color.LightGray)
    ) {
        Text(
            "First Text",
            modifier = Modifier
                .background(Color(0xffF44336)),
            color = Color.White
        )
        Text(
            "Second Text",
            modifier = Modifier
                .background(Color(0xff9C27B0)),
            color = Color.White
        )
        Spacer(modifier = Modifier.weight(1f))
        Text(
            "Third Text",
            modifier = Modifier
                .background(Color(0xff2196F3)),
            color = Color.White
        )
    }

结果: 输入图像描述

在这个使用布局的例子中,你应该考虑如何使用约束来测量你的可测量对象及总宽度和高度。这需要一点练习,但你可以得到更独特的设计,并且使用更少的工作(更优化)的组合件而不是预先准备好的组件。在这里,我将布局设置为最大宽度,因此无论你分配哪个宽度,它都会占据整个宽度。这只是为了演示,你可以根据自己的需求在layout中设置最大宽度或高度。


2
设置视图的特定高度似乎是一个非常糟糕的想法。 - Marty Miller
这只是为了演示。在上面的例子中,拥有固定高度并不是主要问题。上面的例子是关于使用带有Modifier.weightSpacer将最后一个可组合放置在父可组合底部,或者创建一个自定义可组合并使用Layout放置placeables的内容。 - Thracian

35

有很多种方法可以做到这一点。

您可以使用带有verticalArrangement = Arrangement.SpaceBetween的列,将weight(1f,false)分配给最后一行:

  Column(
     Modifier.fillMaxHeight(),
     verticalArrangement = Arrangement.SpaceBetween) {
     
     //All elements 
     Column {

        // RED BOX
        
        //...
        Spacer(
            modifier = Modifier
                .fillMaxWidth()
                .background(Green)
                .height(15.dp)
        )

       //... Green box
    }

    //LAST ROW
    Row(
        modifier = Modifier
            .weight(1f, false)
    ) {
        //...
    }
 }

在这里输入图片描述


1
如果我的内部列有 verticalScroll(),它就无法工作。是否有办法在可滚动内容中实现类似的情况? - Arpit Patel

4

这是对我有效的方法:

结构大致如下:

Column // arrangement = Arrangement.SpaceBetween
  Column
    Row 1
    Row 2
    Row 3
  Row 4

@Preview(showSystemUi = true)
@Composable
fun AlignBottomExample() {
    Column(
        modifier = Modifier.fillMaxWidth(),
        verticalArrangement = Arrangement.SpaceBetween
    ) {

        Column() {
            Row(
                modifier = Modifier.height(100.dp)
                    .background(Color.Magenta)
                    .fillMaxWidth(),
            ) {
                Text(text = "Row 1")
            }
            Row(
                modifier = Modifier.height(100.dp)
                    .background(Color.Cyan)
                    .fillMaxWidth(),
            ) {
                Text(text = "Row 2")
            }
            Row(
                modifier = Modifier.height(100.dp)
                    .background(Color.Yellow)
                    .fillMaxWidth(),
            ) {
                Text(text = "Row 3")
            }
        }

        Row(
            modifier = Modifier.height(100.dp)
                .background(Color.Green)
                .fillMaxWidth(),
        ) {
            Text(text = "Row 4")
        }
    }
}

enter image description here


1
另一个解决方案是使用脚手架(Scaffold):
Scaffold(
    topBar = { /* you can add top bar content  */ },
    bottomBar = {
        Text("Bottom bar",
            fontSize = 50.sp,
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.Black),
        )
    }
) {
    Text(
        "Main content.",
        fontSize = 50.sp,
        color = Color.White,
        modifier = Modifier
            .fillMaxWidth()
            .fillMaxHeight()
            .background(Color.Gray),

    )
} 

输出: {{link1:输入图像描述}}

我必须登录才能为你投票!兄弟,真不错! - undefined
我感到受宠若惊 <3 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接