设置段落样式

本页介绍了如何为段落设置文本样式。如需设置段落级样式,您可以配置 textAlign 和 lineHeight 等参数,也可以定义自己的 ParagraphStyle。

设置文本对齐方式

借助 textAlign 参数,您可以设置 Text 可组合项表面区域内文本的水平对齐方式。

默认情况下,Text 会根据其内容值选择自然的文字对齐方式:

  • 对于从左到右书写的文字,如拉丁语、西里尔文或朝鲜文,向 Text 容器的左边缘对齐
  • 对于从右到左书写的文字,如阿拉伯语或希伯来语,向 Text 容器的右边缘对齐

@Composable
fun CenterText() {
    Text(
        "Hello World", textAlign = TextAlign.Center, modifier = Modifier.width(150.dnippets.kt

“

如果您想手动设置 Text 可组合项的文字对齐方式,最好分别使用 TextAlign.Start 和 TextAlign.End(而不要使用 TextAlign.Left 和 TextAlign.Right),这样系统就可以根据具体语言的首选文字方向,将您的设置解析为向 Text 的正确边缘对齐。例如,TextAlign.End 对于法语文字将向右侧对齐,而对于阿拉伯语文字则将向左侧对齐,但无论对于哪种文字,TextAlign.Right 都将向右侧对齐。

在一个段落中添加多种样式

如需在段落中添加多种样式,您可以在 AnnotatedString 中使用 ParagraphStyle,该字符串可使用任意注解样式加以注解。 一旦文本的一部分被标记为 ParagraphStyle,该部分就会与其余文本分开,就像在开头和结尾处有换行符一样。

如需详细了解如何在文本中添加多种样式,请参阅在文本中添加多种样式。

AnnotatedString 具有类型安全的构建器,可让您更轻松地创建:buildAnnotatedString。以下代码段使用 buildAnnotatedString 设置 ParagraphStyle:

@Composable
fun ParagraphStyle() {
    Text(
        buildAnnotatedString {
            withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append("Hello\n")
                }
                withStyle(
                    style = SpanStyle(
                        fontWeight = FontWeight.Bold, color = Color.Red
                    )
                ) {
                    append("World\n")
                }
                append("Compose")
       }
    )
}TextSnippets.kt

三个段落采用三种不同的样式:蓝色、红色粗体以及纯黑色

调整行高和内边距

includeFontPadding 是一个旧版属性,它根据第一行文字顶部和最后一行文字底部的字体指标添加额外的内边距。 从 Compose BOM 版本 2024.01.01 开始,includeFontPadding 默认设置为 false,这使得默认文本布局更符合常见设计工具。

配置 lineHeight 的功能并不新鲜。从 Android Q 就开始提供此功能。您可以使用 lineHeight 参数为 Text 配置 lineHeight,该参数可在每行文本中分布行高。然后,您可以使用新的 LineHeightStyle API 来进一步配置此文本的对齐方式,并移除空格。

为了提高精确度,您可能需要使用文本单位“em”(相对字体大小)而不是“sp”(缩放后的像素)来调整 lineHeight。如需详细了解如何选择合适的文本单元,请参阅 TextUnit。

此图片以正上方和正下方的线条为基准显示 lineHeight 的度量值。
图 1. 使用 Alignment 和 Trim 调整 lineHeight 集合中的文本,并根据需要去除多余的空格。

Text(
    text = text,
    style = LocalTextStyle.current.merge(
        TextStyle(
            lineHeight = 2.5.em,
            platformStyle = PlatformTextStyle(
                includeFontPadding = false
            ),
            lineHeightStyle = LineHeightStyle(
                alignment = LineHeightStyle.Alignment.Center,
                trim = LineHeightStyle.Trim.None
            )
        )
    )
)

除了调整 lineHeight 以外,您现在还可以使用 LineHeightStyle API(LineHeightStyle.Alignment 和 LineHeightStyle.Trim)来进一步设置文本居中和样式。(includeFontPadding 必须设置为 false 才能让 Trim 发挥作用)。Alignment 和 Trim 会使用在文本行之间测量到的空间,以便更合理地将其分配给所有行,包括单行文本和文本块的第一行。

LineHeightStyle.Alignment 定义了如何在行高提供的空间内对齐行。在每行中,您可以将文本与顶部、底部、中心或按比例对齐。然后,LineHeightStyle.Trim 可允许您从文本首行顶部或末行底部移除多余空格,这将通过任何 lineHeight 和 Alignment 调整生成。以下示例展示了当对齐居中时 (LineHeightStyle.Alignment.Center),多行文本在各种 LineHeightStyle.Trim 配置下的外观。

展示 LineHeightStyle.Trim.None 的图片 展示 LineHeightStyle.Trim.Both 的图片
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
展示 LineHeightStyle.Trim.FirstLineTop 的图片 展示 LineHeightStyle.Trim.LastLineBottom 的图片
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

如需详细了解此变更的背景信息、includeFontPadding 在 View 系统中的工作原理、我们对 Compose 所做的更改以及新的 LineHeightStyle API,请参阅修复 Compose Text 中的字体内边距问题博文。

插入换行符

LineBreak API 定义了将文本拆分为多行的条件。您可以在 Text 可组合项的 TextStyle 块中指定所需的换行类型。预设的换行类型包括:

  • Simple - 快速、基本的换行。建议用于文本输入字段。
  • Heading - 采用更宽松的换行规则进行换行。建议用于短文本,例如标题。
  • Paragraph - 换行速度较慢,但质量较高,可提高可读性。 建议用于较长的文本,例如段落。

以下代码段同时使用 Simple 和 Paragraph 来指定长文本块的换行行为:

TextSample(
    samples = mapOf(
        "Simple" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Simple
                )
            )
        },
        "Paragraph" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph
                )
             )
)TextSnippets.kt

一个文本块显示简单的换行策略,另一个文本块显示段落优化的换行策略。采用简单换行策略的文本块在行长方面具有更大的可变性。
图 1. 采用简单换行策略的文本块(顶部)与采用段落优化换行的文本块(底部)。

在上面的输出中,请注意,Paragraph 换行行为产生的视觉平衡效果比 Simple 换行更好。

自定义换行符

您还可以使用 Strategy 参数构建自己的 LineBreak 配置。Strategy 可以是以下任意一项:

  • Balanced - 尝试平衡文本的行长,如果启用了自动连字符,还会应用自动连字符。建议在手表等小屏幕上使用,以最大限度地增加显示的文本量。
  • HighQuality - 优化段落,使文本更易于阅读,包括连字符(如果已启用)。(对于非 Balanced 或 Simple 的所有内容,此选项应为默认选项。)
  • Simple - 基本、快速策略。如果启用,则仅对无法单独容纳在一整行中的字词进行连字符处理。在编辑文本时非常有用,可避免在输入时改变位置。

以下代码段展示了采用默认设置的段落与采用 Balanced 换行策略针对小屏幕进行优化的段落之间的区别:

TextSample(
    samples = mapOf(
        "Balanced" to {
            val smallScreenAdaptedParagraph =
                LineBreak.Paragraph.copy(strategy = LineBreak.Strategy.Balanced)
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = smallScreenAdaptedParagraph
                )
            )
        },
        "Default" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default
             )
)TextSnippets.kt

一个段落采用平衡换行策略,另一个段落未采用任何策略。与默认策略相比,采用平衡换行策略的段落具有更一致的行长。
图 2. 使用 Balanced 换行策略设置格式的段落(顶部)与未使用换行策略设置格式的段落。

CJK 注意事项

您还可以使用 Strictness 和 WordBreak API 自定义 LineBreak,这些 API 是专门针对 CJK 语言设计的。 在非 CJK 语言中,您可能不一定能看到这些 API 的效果。总体而言,换行规则是根据语言区域定义的。

Strictness 通过以下属性描述换行的严格程度:

  • Default - 语言区域的默认换行规则。可能对应于 Normal 或 Strict。
  • Loose - 限制性最低的规则。适合短行。
  • Normal - 最常见的换行规则。
  • Strict - 最严格的换行规则。

WordBreak 定义了应如何使用以下属性在字词中插入换行符:

  • Default - 语言区域的默认换行规则。
  • Phrase - 根据短语换行。

以下代码段对日语文本使用了 Strict 严格性和 Phrase 换行设置:

val customTitleLineBreak = LineBreak(
    strategy = LineBreak.Strategy.HighQuality,
    strictness = LineBreak.Strictness.Strict,
    wordBreak = LineBreak.WordBreak.Phrase
)
Text(
    text = "あなたに寄り添う最先端のテクノロジー。",
    modifier = Modifier.width(250.dp),
    fontSize = 14.sp,
    style = TextStyle.Default.copy(
        lineBreak = customTitleLineBrenippets.kt

采用 Strictness 和 WordBreak 设置的日语文本与默认文本。
图 3. 使用 Strictness 和 WordBreak 设置设置格式的文本(顶部)与仅使用 LineBreak.Heading 设置格式的文本(底部)。

使用连字符连接跨行拆分的文本

借助 Hyphens API,您可以向应用添加连字符支持。连字符是指插入一个类似破折号的标点符号,表示一个单词在多行文本中被拆分。启用后,系统会在字词音节之间的适当连字符位置添加连字符。

默认情况下,连字符功能处于停用状态。如需启用连字符,请在 TextStyle 代码块中添加 Hyphens.Auto 作为参数:

TextSample(
    samples = mapOf(
        "Hyphens - None" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.None
                )
            )
        },
        "Hyphens - Auto" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.Auto
                )
             )
)TextSnippets.kt

一个未启用连字符的段落和一个启用了连字符的段落。
  启用连字符后,单词会使用连字符连接并拆分为两行。
图 4. 未启用连字符的段落(上)与启用连字符的段落(下)。

启用后,仅在以下情况下才会进行连字符处理:

  • 某个字词无法在一行中完整显示。如果您使用 Simple 换行策略,则只有在行长度小于单个单词时,才会对单词进行连字符化。
  • 在设备上设置适当的语言区域,因为系统会使用系统中的字典来确定适当的连字符。