Compose 修饰符

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

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

修饰符是标准的 Kotlin 对象。您可以通过调用某个 Modifier 类函数来创建修饰符:

import androidx.compose.ui.Modifier

@Composable
private fun Greeting(name: String) {
  Column(modifier = Modifier.padding(24.dp)) {
    Text(text = "Hello,")
    Text(text = name)
  }
}

彩色背景上有两行文字,文字周围有内边距。

您可以将以下函数连在一起以将其组合起来:

@Composable
private fun Greeting(name: String) {
  Column(modifier = Modifier
    .padding(24.dp)
    .fillMaxWidth()
  ) {
    Text(text = "Hello,")
    Text(text = name)
  }
}

文字后面的彩色背景现已延伸覆盖设备屏幕的全宽。

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

  • padding 在元素周围留出空间。
  • fillMaxWidth 使可组合项填充其父项为它提供的最大宽度。

最佳做法是让所有可组合项接受 modifier 参数,并将该修饰符传递给其发出界面元素的第一个子项。这样做可以提高代码的可重用性,使其行为更可预测且更直观。如需了解详情,请参阅 Compose API 指南:接受元素和遵循修饰符参数

修饰符顺序很重要

修饰符函数的顺序非常重要。由于每个函数都会对上一个函数返回的 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 提供了一个内置修饰符列表,可帮助您修饰或扩充可组合项。以下是一些用于调整布局的常见修饰符。

内边距和尺寸

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

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(/*...*/)
        Column { /*...*/ }
    }
}

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

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.requiredSize(150.dp)
        )
        Column { /*...*/ }
    }
}

子图片的尺寸大于其父项的约束条件

在此示例中,即使父项的 height 设置为 100.dpImage 的高度还是 150.dp,因为 requiredSize 修饰符优先级较高。

如果您希望子布局填充父项允许的所有可用高度,请添加 fillMaxHeight 修饰符(Compose 还提供了 fillMaxSizefillMaxWidth):

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.size(width = 400.dp, height = 100.dp)
    ) {
        Image(
            /*...*/
            modifier = Modifier.fillMaxHeight()
        )
        Column { /*...*/ }
    }
}

图片高度与其父项相同

如需在整个元素周围全添加内边距,请设置 padding 修饰符。

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

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(
                text = artist.name,
                modifier = Modifier.paddingFromBaseline(top = 50.dp)
            )
            Text(artist.lastSeenOnline)
        }
    }
}

上方有内边距的文本

偏移量

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

@Composable
fun ArtistCard(artist: Artist) {
    Row(/*...*/) {
        Column {
            Text(artist.name)
            Text(
                text = artist.lastSeenOnline,
                modifier = Modifier.offset(x = 4.dp)
            )
        }
    }
}

文本移至其父容器的右侧

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

Compose 中的类型安全

在 Compose 中,有些修饰符仅适用于某些可组合项的子项。例如,如果您希望使某个子项与父项 Box 同样大,而不影响 Box 尺寸,请使用 matchParentSize 修饰符。

Compose 通过自定义作用域强制实施此类型安全机制。例如,matchParentSize 仅在 BoxScope 中可用。因此,仅当在 Box 中使用子项时,才能使用此修饰符。

限定作用域的修饰符会将父项应知晓的关于子项的一些信息告知父项。这些修饰符通常称为“父项数据修饰符”。它们的内部构件与通用修饰符不同,但从使用角度来看,这些差异并不重要。

Box 中的 matchParentSize

如上所述,如果您希望子布局与父项 Box 尺寸相同而不影响 Box 的尺寸,请使用 matchParentSize 修饰符。

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

在以下示例中,子项 Spacer 从其父项 Box 获取自己的尺寸,在这种情况下,后者又会从其最大的子项 ArtistCard 中获取自己的尺寸。

@Composable
fun MatchParentSizeComposable() {
    Box {
        Spacer(Modifier.matchParentSize().background(Color.LightGray))
        ArtistCard()
    }
}

填充容器的灰色背景

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

填充屏幕的灰色背景

Row 和 Column 中的 weight

如前文的内边距和尺寸部分所述,默认情况下,可组合项的尺寸由其封装的内容定义。您可以使用仅可在 RowScopeColumnScope 中使用的 weight 修饰符,将可组合项的尺寸设置为可在其父项内灵活调整。

让我们以包含两个 Box 可组合项的 Row 为例。第一个框的 weight 是第二个框的两倍,因此其宽度也相差两倍。由于 Row 的宽度为 210.dp,因此第一个 Box 的宽度为 140.dp,第二个的宽度为 70.dp

@Composable
fun ArtistCard(/*...*/) {
    Row(
        modifier = Modifier.fillMaxWidth()
    ) {
        Image(
            /*...*/
            modifier = Modifier.weight(2f)
        )
        Column(
            modifier = Modifier.weight(1f)
        ) {
            /*...*/
        }
    }
}

图片宽度是文字宽度的两倍

了解详情

我们提供了修饰符的完整列表及其参数和范围。