Compose 中的布局

Jetpack Compose 可让您更轻松地设计和构建应用的界面。本文档介绍了 Compose 为了帮助您布置界面元素而提供的一些构建块,并向您展示了如何在需要时构建更专业的布局。

可组合函数是 Compose 的基本构建块。可组合函数是一种发出 Unit 的函数,用于描述界面中的某一部分。该函数接受一些输入并生成屏幕上显示的内容。如需详细了解可组合项,请参阅 Compose 构思模型文档。

一个可组合函数可能会发出多个界面元素。不过,如果您未提供有关如何排列这些元素的指导,Compose 可能会以您不喜欢的方式排列它们。例如,以下代码会生成两个文本元素:

@Composable
fun ArtistCard() {
    Text("Alfred Sisley")
    Text("3 minutes ago")
}

如果您未提供有关如何排列这两个文本元素的指导,Compose 会将它们堆叠在一起,使其无法阅读:

两个文本元素相互叠加,使文本无法阅读

Compose 提供了一系列现成可用的布局来帮助您排列界面元素,并且可让您轻松地定义您自己的更专业的布局。

标准布局组件

在许多情况下,您只需使用 Compose 的标准布局元素即可。

使用 Column 可将多个项垂直地放置在屏幕上。

@Composable
fun ArtistCard() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

两个文本元素按列布局排列,因此文本清晰易读

同样,使用 Row 可将多个项水平地放置在屏幕上。ColumnRow 都支持配置它们所含元素的对齐方式。

@Composable
fun ArtistCard(artist: Artist) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Image(/*...*/)
        Column {
            Text(artist.name)
            Text(artist.lastSeenOnline)
        }
    }
}

示例显示了一个更复杂的布局,一列文本元素旁边有一个小图形

使用 Box 可将一个元素放在另一个元素上。

比较三个简单的布局可组合项:Column、Row 和 Box

通常,您只需要这些构建块。您可以自行编写可组合函数,将这些布局组合成更精美的布局,以适合您的应用。

如需在 Row 中设置子项的位置,请设置 horizontalArrangementverticalAlignment 参数。对于 Column,请设置 verticalArrangementhorizontalAlignment 参数:

@Composable
fun AlignInRow() {
    Row(
        modifier = Modifier
            .size(150.dp)
            .background(Color.Yellow),
        horizontalArrangement = Arrangement.End,
        verticalAlignment = Alignment.CenterVertically
    ) {
        Box(Modifier.size(50.dp).background(Color.Red))
        Box(Modifier.size(50.dp).background(Color.Blue))
    }
}

一个大的黄色方形,中间横放着一排方框

修饰符

借助修饰符,您可以修饰或扩充可组合项。您可以使用修饰符来执行以下操作:

  • 更改可组合项的大小、布局、行为和外观
  • 添加信息,如无障碍标签
  • 处理用户输入
  • 添加高级互动,如使元素可点击、可滚动、可拖动或可缩放

修饰符是标准的 Kotlin 对象。您可以通过调用某个 Modifier 类函数来创建修饰符。您可以将以下函数连在一起以将其组合起来:

@Composable
fun ArtistCard(
    artist: Artist,
    onClick: () -> Unit
) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) { /*...*/ }
        Spacer(Modifier.size(padding))
        Card(elevation = 4.dp) { /*...*/ }
    }
}

一个更复杂的布局,使用修饰符来更改图形的排列方式,以及哪些区域响应用户输入

请注意,在上面的代码中,结合使用了不同的修饰符函数。

  • clickable 使可组合项响应用户输入,并显示涟漪。
  • padding 在元素周围留出空间。
  • fillMaxWidth 使可组合项填充其父项为它提供的最大宽度。
  • size() 指定元素的首选宽度和高度。

修饰符函数的顺序非常重要。由于每个函数都会对上一个函数返回的 Modifier 进行更改,因此顺序会影响最终结果。让我们来看看这方面的一个示例:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .clickable(onClick = onClick)
            .padding(padding)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

整个区域(包括围绕边缘的内边距)都响应点击操作

在上面的代码中,整个区域(包括周围的内边距)都是可点击的,因为 padding 修饰符应用在 clickable 修饰符后面。如果修饰符顺序相反,由 padding 添加的空间就不会响应用户输入:

@Composable
fun ArtistCard(/*...*/) {
    val padding = 16.dp
    Column(
        Modifier
            .padding(padding)
            .clickable(onClick = onClick)
            .fillMaxWidth()
    ) {
        // rest of the implementation
    }
}

围绕布局边缘的内边距不再响应点击操作

内置修饰符

Jetpack Compose 提供了一个内置修饰符列表,可帮助您修饰或扩充可组合项。下面列出的修饰符可满足大多数常见用例的需要:

内边距和尺寸

如需设置围绕可组合项的内边距,请添加 padding 修饰符:

@Composable
fun PaddedComposable() {
    Text("Hello World", modifier = Modifier.background(Color.Green).padding(20.dp))
}

四周都添加了内边距的文本

默认情况下,Compose 中提供的布局会封装其子项。但是,您可以使用 size 修饰符设置尺寸:

@Composable
fun SizedComposable() {
    Box(Modifier.size(100.dp, 100.dp).background(Color.Red))
}

请注意,如果指定的尺寸不符合来自布局父项的约束条件,则可能不会采用该尺寸。如果您希望可组合项的尺寸固定不变,而不考虑传入的约束条件,请使用 requiredSize 修饰符:

@Composable
fun FixedSizeComposable() {
    Box(Modifier.size(90.dp, 150.dp).background(Color.Green)) {
        Box(Modifier.requiredSize(100.dp, 100.dp).background(Color.Red))
    }
}

两个矩形叠加在一起,较宽的红色矩形在较窄的绿色矩形背景上面

在此示例中,即使父宽度设为 90.dp,内部 Box 的宽度还是 100.dp,因为内部框的 requiredSize 修饰符优先级较高。

如果您希望子布局填充父项允许的所有可用空间,请添加 fillMaxSize 修饰符(Compose 还提供 fillMaxHeightfillMaxWidth):

@Composable
fun FillSizeComposable() {
    Box(Modifier.background(Color.Green).size(50.dp).padding(10.dp)) {
        Box(Modifier.background(Color.Blue).fillMaxSize())
    }
}

较大绿色正方形中间有一个蓝色正方形

如果您希望将子布局的尺寸设置为与父 Box 相同,但不影响 Box 的尺寸,请使用 matchParentSize 修饰符。

请注意,matchParentSize 仅在 Box 作用域内可用,这意味着它仅适用于 Box 可组合项的直接子项

在下面的示例中,内部 Spacer 从其父 Box 获取自己的尺寸,而后者又从其包含的 Text 获取自己的尺寸。

@Composable
fun MatchParentSizeComposable() {
    Box {
        Spacer(Modifier.matchParentSize().background(Color.Green))
        Text("Hello World")
    }
}

填满容器的文本

如果使用 fillMaxSize 代替 matchParentSizeSpacer 将占用父项允许的所有可用空间,反过来使父项展开并填满所有可用空间。

较大绿色正方形顶角处有较小的文本

如需在文本基线上方添加内边距,以实现从布局顶部到基线保持特定距离,请使用 paddingFromBaseline 修饰符:

@Composable
fun TextWithPaddingFromBaseline() {
    Box(Modifier.background(Color.Yellow)) {
        Text("Hi there!", Modifier.paddingFromBaseline(top = 32.dp))
    }
}

上方有内边距的文本

偏移量

要相对于原始位置放置布局,请添加 offset 修饰符,并在 x 轴和 y 轴中设置偏移量。偏移量可以是正数,也可以是非正数。paddingoffset 之间的区别在于,向可组合项添加 offset 不会改变其测量结果:

@Composable
fun OffsetComposable() {
    Box(Modifier.background(Color.Yellow).size(width = 150.dp, height = 70.dp)) {
        Text(
            "Layout offset modifier sample",
            Modifier.offset(x = 15.dp, y = 20.dp)
        )
    }
}

文本移至其父容器的右侧

offset 修饰符根据布局方向水平应用。在从左到右的上下文中,正 offset 会将元素向右移,而在从右到左的上下文中,它会将元素向左移。如果您需要设置偏移量,而不考虑布局方向,请参阅 absoluteOffset 修饰符,其中,正偏移值始终将元素向右移。

可滚动布局

如需详细了解可滚动布局,请参阅 Compose 手势文档。

自适应布局

在设计布局时,应考虑不同的屏幕方向和设备类型尺寸。Compose 提供了一些开箱即用的机制,可帮助您根据各种屏幕配置调整可组合项的布局。

RowColumn 中的 weight 修饰符

正如上一节的内边距和尺寸所述,可组合项的尺寸默认情况下由其封装的内容定义。您可以将可组合项的尺寸设置为可在其父项内灵活调整。让我们以包含两个 Box 可组合项的 Row 为例。第一个框的 weight 是第二个框的两倍,因此其宽度也相差两倍。由于 Row 的宽度为 210.dp,因此第一个 Box 的宽度为 140.dp,第二个的宽度为 70.dp

@Composable
fun FlexibleComposable() {
    Row(Modifier.width(210.dp)) {
        Box(Modifier.weight(2f).height(50.dp).background(Color.Blue))
        Box(Modifier.weight(1f).height(50.dp).background(Color.Red))
    }
}

两个矩形并排显示,较宽的蓝色矩形位于较窄的红色矩形左侧

约束条件

如需了解来自父项的约束条件并相应地设计布局,您可以使用 BoxWithConstraints。您可以在内容 lambda 的作用域内找到测量约束条件。您可以使用这些测量约束条件,为不同的屏幕配置组成不同的布局:

@Composable
fun WithConstraintsComposable() {
    BoxWithConstraints {
        Text("My minHeight is $minHeight while my maxWidth is $maxWidth")
    }
}
基于槽位的布局

Compose 提供了大量基于 Material Design 的可组合项以及 androidx.compose.material:material 依赖项(在 Android Studio 中创建 Compose 项目时提供),旨在简化界面的构建。诸如 DrawerFloatingActionButtonTopAppBar 之类的元素都有提供。

Material 组件大量使用槽位 API,这是 Compose 引入的一种模式,它在可组合项之上带来一层自定义设置。这种方法使组件变得更加灵活,因为它们接受可以自行配置的子元素,而不必公开子元素的每个配置参数。槽位会在界面中留出空白区域,让开发者按照自己的意愿来填充。例如,下面是您可以在 TopAppBar 中自定义的槽位:

显示 Material Components 应用栏中的可用槽位的图表

可组合项通常采用 content 可组合 lambda (content: @Composable () -> Unit)。槽位 API 会针对特定用途公开多个 content 参数。例如,TopAppBar 可让您为 titlenavigationIconactions 提供内容。

例如,Scaffold 可让您实现具有基本 Material Design 布局结构的界面。Scaffold 可以为最常见的顶级 Material 组件(如 TopAppBarBottomAppBarFloatingActionButtonDrawer)提供槽位。通过使用 Scaffold,可轻松确保这些组件得到适当放置且正确地协同工作。

JetNews 示例应用,该应用使用 Scaffold 确定多个元素的位置

@Composable
fun HomeScreen(/*...*/) {
    Scaffold(
        drawerContent = { /*...*/ },
        topBar = { /*...*/ },
        bodyContent = { /*...*/ }
    )
}

ConstraintLayout

ConstraintLayout 有助于根据可组合项的相对位置将它们放置在屏幕上,它是使用多个嵌套 RowColumnBox 和自定义布局元素的替代方案。在实现对齐要求比较复杂的较大布局时,ConstraintLayout 很有用,但在创建简单布局时,首选 ColumnRow

如需使用 Compose 中的 ConstraintLayout,您需要在 build.gradle 中添加以下依赖项:

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha03"

Compose 中的 ConstraintLayout 支持 DSL

  • 引用是使用 createRefs()createRefFor() 创建的,ConstraintLayout 中的每个可组合项都需要有与之关联的引用。
  • 约束条件是使用 constrainAs() 修饰符提供的,该修饰符将引用作为参数,可让您在主体 lambda 中指定其约束条件。
  • 约束条件是使用 linkTo() 或其他有用的方法指定的。
  • parent 是一个现有的引用,可用于指定对 ConstraintLayout 可组合项本身的约束条件。

下面是使用 ConstraintLayout 的可组合项的示例:

@Composable
fun ConstraintLayoutContent() {
    ConstraintLayout {
        // Create references for the composables to constrain
        val (button, text) = createRefs()

        Button(
            onClick = { /* Do something */ },
            // Assign reference "button" to the Button composable
            // and constrain it to the top of the ConstraintLayout
            modifier = Modifier.constrainAs(button) {
                top.linkTo(parent.top, margin = 16.dp)
            }
        ) {
            Text("Button")
        }

        // Assign reference "text" to the Text composable
        // and constrain it to the bottom of the Button composable
        Text("Text", Modifier.constrainAs(text) {
            top.linkTo(button.bottom, margin = 16.dp)
        })
    }
}

此代码使用 16.dp 的外边距来约束 Button 顶部到父项的距离,同样使用 16.dp 的外边距来约束 TextButton 底部的距离。

显示了按 ConstraintLayout 排列的按钮和文本元素

如需查看有关如何使用 ConstraintLayout 的更多示例,请参考布局 Codelab

Decoupled API

ConstraintLayout 示例中,约束条件是在应用它们的可组合项中使用修饰符以内嵌方式指定的。不过,在某些情况下,最好将约束条件与应用它们的布局分离开来。例如,您可能会希望根据屏幕配置来更改约束条件,或在两个约束条件集之间添加动画效果。

对于此类情况,您可以通过不同的方式使用 ConstraintLayout

  1. ConstraintSet 作为参数传递给 ConstraintLayout
  2. 使用 layoutId 修饰符将在 ConstraintSet 中创建的引用分配给可组合项。
@Composable
fun DecoupledConstraintLayout() {
    BoxWithConstraints {
        val constraints = if (minWidth < 600.dp) {
            decoupledConstraints(margin = 16.dp) // Portrait constraints
        } else {
            decoupledConstraints(margin = 32.dp) // Landscape constraints
        }

        ConstraintLayout(constraints) {
            Button(
                onClick = { /* Do something */ },
                modifier = Modifier.layoutId("button")
            ) {
                Text("Button")
            }

            Text("Text", Modifier.layoutId("text"))
        }
    }
}

private fun decoupledConstraints(margin: Dp): ConstraintSet {
    return ConstraintSet {
        val button = createRefFor("button")
        val text = createRefFor("text")

        constrain(button) {
            top.linkTo(parent.top, margin = margin)
        }
        constrain(text) {
            top.linkTo(button.bottom, margin)
        }
    }
}

然后,当您需要更改约束条件时,只需传递不同的 ConstraintSet 即可。

自定义布局

在 Compose 中,界面元素由可组合函数表示,此类函数在被调用后会发出一部分界面,这部分界面随后会被添加到呈现在屏幕上的界面树中。每个界面元素都有一个父元素,还可能有多个子元素。此外,每个元素在其父元素中都有一个位置,指定为 (x, y) 位置;也都有一个尺寸,指定为 widthheight

父元素定义其子元素的约束条件。元素需要在这些约束条件内定义尺寸。约束条件可限制元素的最小和最大 widthheight。如果某个元素有子元素,它可能会测量每个子元素,以帮助确定其尺寸。一旦某个元素确定并报告了它自己的尺寸,就有机会定义如何相对于自身放置它的子元素,如创建自定义布局中所详述。

单遍测量对性能有利,使 Compose 能够高效地处理较深的界面树。如果某个元素测量了它的子元素两次,而该子元素又测量了它的一个子元素两次,依此类推,那么一次尝试布置整个界面就不得不做大量的工作,这将很难让应用保持良好的性能。不过,有时除了子元素的单遍测量告知您的信息之外,您确实还需要一些额外的信息。有一些方法可以有效地处理这样的情况,这些方法在固有特性测量部分进行了介绍。

使用布局修饰符

您可以使用 layout 修饰符来修改元素的测量和布局方式。Layout 是一个 lambda;它的参数包括您可以测量的元素(以 measurable 的形式传递)以及该可组合项的传入约束条件(以 constraints 的形式传递)。自定义布局修饰符可能如下所示:

fun Modifier.customLayoutModifier(...) =
    this.layout { measurable, constraints ->
        ...
    })

假设我们在屏幕上显示 Text,并控制从顶部到第一行文本基线的距离。这正是 paddingFromBaseline 修饰符的作用,我们在这里将其作为一个示例来实现。为此,请使用 layout 修饰符将可组合项手动放置在屏幕上。Text 上内边距设为 24.dp 时的预期行为如下:

显示了正常界面内边距与文本内边距之间的差异,前者设置元素的间距,后者设置从一条基线到下一条基线的间距

生成该间距的代码如下:

fun Modifier.firstBaselineToTop(
    firstBaselineToTop: Dp
) = layout { measurable, constraints ->
    // Measure the composable
    val placeable = measurable.measure(constraints)

    // Check the composable has a first baseline
    check(placeable[FirstBaseline] != AlignmentLine.Unspecified)
    val firstBaseline = placeable[FirstBaseline]

    // Height of the composable with padding - first baseline
    val placeableY = firstBaselineToTop.roundToPx() - firstBaseline
    val height = placeable.height + placeableY
    layout(placeable.width, height) {
        // Where the composable gets placed
        placeable.placeRelative(0, placeableY)
    }
}

下面对该代码中发生的过程进行了说明:

  1. measurable lambda 参数中,您需要通过调用 measurable.measure(constraints) 来测量以可测量参数表示的 Text
  2. 您需要通过调用 layout(width, height) 方法指定可组合项的尺寸,该方法还会提供一个用于放置被封装元素的 lambda。在本例中,它是最后一条基线和增加的上内边距之间的高度。
  3. 您通过调用 placeable.place(x, y) 将被封装的元素放到屏幕上。如果未放置被封装的元素,它们将不可见。y 位置对应于上内边距,即文本的第一条基线的位置。

如需验证这段代码是否可以发挥预期的作用,请在 Text 上使用以下修饰符:

@Preview
@Composable
fun TextWithPaddingToBaselinePreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.firstBaselineToTop(32.dp))
    }
}

@Preview
@Composable
fun TextWithNormalPaddingPreview() {
    MyApplicationTheme {
        Text("Hi there!", Modifier.padding(top = 32.dp))
    }
}

文本元素的多种预览;一种显示元素之间的普通内边距,另一种显示从一条基线到下一条基线的内边距

创建自定义布局

layout 修饰符仅更改调用可组合项。如需测量和布置多个可组合项,请改用 Layout 可组合项。此可组合项允许您手动测量和布置子项。ColumnRow 等所有较高级别的布局都使用 Layout 可组合项构建而成。

我们来构建一个非常基本的 Column。大多数自定义布局都遵循以下模式:

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable() () -> Unit
) {
    Layout(
        modifier = modifier,
        children = content
    ) { measurables, constraints ->
        // measure and position children given constraints logic here
    }
}

layout 修饰符类似,measurables 是需要测量的子项的列表,而 constraints 是来自父项的约束条件。按照与前面相同的逻辑,可按如下方式实现 MyBasicColumn

@Composable
fun MyBasicColumn(
    modifier: Modifier = Modifier,
    content: @Composable() () -> Unit
) {
    Layout(
        modifier = modifier,
        content = content
    ) { measurables, constraints ->
        // Don't constrain child views further, measure them with given constraints
        // List of measured children
        val placeables = measurables.map { measurable ->
            // Measure each children
            measurable.measure(constraints)
        }

        // Set the size of the layout as big as it can
        layout(constraints.maxWidth, constraints.maxHeight) {
            // Track the y co-ord we have placed children up to
            var yPosition = 0

            // Place children in the parent layout
            placeables.forEach { placeable ->
                // Position item on the screen
                placeable.placeRelative(x = 0, y = yPosition)

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

可组合子项受 Layout 约束条件(没有 minHeight 约束条件)的约束,它们的放置基于前一个可组合项的 yPosition

该自定义可组合项的使用方式如下:

@Composable
fun CallingComposable(modifier: Modifier = Modifier) {
    MyBasicColumn(modifier.padding(8.dp)) {
        Text("MyBasicColumn")
        Text("places items")
        Text("vertically.")
        Text("We've done it by hand!")
    }
}

几个文本元素依次堆叠成一列。

布局方向

您可以通过更改 LocalLayoutDirection composeLocal 来更改可组合项的布局方向。

如果您要将可组合项手动放置在屏幕上,则 LayoutDirectionlayout 修饰符或 Layout 可组合项的 LayoutScope 的一部分。

使用 layoutDirection 时,应使用 place 放置可组合项。与 place 方法不同,place 不会根据阅读方向(从左到右与从右到左)发生变化。

固有特性测量

Compose 有一项规则,即,子项只能测量一次,测量两次就会引发运行时异常。但是,有时需要先收集一些关于子项的信息,然后再测量子项。

借助固有特性,您可以先查询子项,然后再进行实际测量。

对于可组合项,您可以查询其 intrinsicWidthintrinsicHeight

  • (min|max)IntrinsicWidth:给定此高度,可以正确绘制内容的最小/最大宽度是多少?
  • (min|max)IntrinsicHeight:给定此宽度,可以正确绘制内容的最小/最大高度是多少?

例如,如果您查询具有无限 widthTextminIntrinsicHeight,它将返回 Textheight,就好像该文本是在单行中绘制的一样。

固有特性的实际运用

假设我们需要创建一个可组合项,该可组合项在屏幕上显示两个用分隔线隔开的文本,如下所示:

两个文本元素并排显示,中间用垂直分隔线隔开

我们该怎么做?我们可以将两个 Text 放在同一 Row,并在其中最大程度地扩展,另外在中间放置一个 Divider。我们需要将分隔线的高度设置为与最高的 Text 相同,粗细设置为 width = 1.dp

@Composable
fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) {
    Row(modifier = modifier) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.Start),
            text = text1
        )

        Divider(color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp))
        Text(
            modifier = Modifier
                .weight(1f)

                .padding(end = 4.dp)
                .wrapContentWidth(Alignment.End),

            text = text2
        )
    }
}

@Preview
@Composable
fun TwoTextsPreview() {
    LayoutsCodelabTheme {
        Surface {
            TwoTexts(text1 = "Hi", text2 = "there")
        }
    }
}

预览时,我们发现分隔线扩展到整个屏幕,这并不是我们想要的效果:

两个文本元素并排显示,中间用分隔线隔开,但分隔线向下延伸到文本底部下方

之所以出现这种情况,是因为 Row 会逐个测量每个子项,并且 Text 的高度不能用于限制 Divider。我们希望 Divider 以一个给定的高度来填充可用空间。为此,我们可以使用 height(IntrinsicSize.Min) 修饰符。

height(IntrinsicSize.Min) 可将其子项的高度强行调整为最小固有高度。由于该修饰符具有递归性,因此它将查询 Row 及其子项 minIntrinsicHeight

将其应用到代码中,就能达到预期的效果:

@Composable
fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) {
    Row(modifier = modifier.preferredHeight(IntrinsicSize.Min)) {
        Text(
            modifier = Modifier
                .weight(1f)
                .padding(start = 4.dp)
                .wrapContentWidth(Alignment.Start),
            text = text1
        )

        Divider(color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp))
        Text(
            modifier = Modifier
                .weight(1f)

                .padding(end = 4.dp)
                .wrapContentWidth(Alignment.End),
            text = text2
        )
    }
}

@Preview
@Composable
fun TwoTextsPreview() {
    LayoutsCodelabTheme {
        Surface {
            TwoTexts(text1 = "Hi", text2 = "there")
        }
    }
}

预览如下:

两个文本元素并排显示,中间用垂直分隔线隔开

Row 可组合项的 minIntrinsicHeight 将作为其子项的最大 minIntrinsicHeightDivider element'sminIntrinsicHeight 为 0,因为如果没有给出约束条件,它不会占用任何空间;如果给出特定 widthText minIntrinsicHeight 将为文本的高度。因此,Row 元素的 height 约束条件将为 Text 的最大 minIntrinsicHeight。而 Divider 会将其 height 扩展为 Row 给定的 height 约束条件。

了解详情

如需了解详情,请参阅 Jetpack Compose 中的布局 Codelab