段落样式

此页面介绍如何为段落文本设置样式。要设置段落级样式,您可以配置 textAlignlineHeight 等参数,或定义自己的 ParagraphStyle

设置文本对齐方式

textAlign 参数允许您设置文本在 Text 可组合项表面区域内的水平对齐方式

默认情况下,Text 将根据其内容值选择自然文本对齐方式

  • 对于从左到右的字母(如拉丁文、西里尔文或韩文),文本对齐到 Text 容器的左边缘
  • 对于从右到左的字母(如阿拉伯文或希伯来文),文本对齐到 Text 容器的右边缘

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

The words

如果您想手动设置 Text 可组合项的文本对齐方式,建议使用 TextAlign.StartTextAlign.End,而不是 TextAlign.LeftTextAlign.Right,因为它们会根据首选语言文本方向解析为 Text 可组合项的右边缘。例如,TextAlign.End 对于法文文本向右对齐,对于阿拉伯文文本向左对齐,但 TextAlign.Right 无论使用何种字母都向右对齐。

在段落中添加多种样式

要在段落中添加多种样式,您可以在 AnnotatedString 中使用 ParagraphStyleAnnotatedString 可以用任意注解进行注解。一旦文本的某一部分被 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")
            }
        }
    )
}

Three paragraphs in three different styles: Blue, red and bold, and plain black

调整行高和内边距

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

配置 lineHeight 的能力并非新功能——它自 Android Q 起就已可用。您可以使用 lineHeight 参数为 Text 配置 lineHeight,该参数将行高分布在文本的每一行中。然后,您可以使用新的 LineHeightStyle API 进一步配置此文本在该空间内的对齐方式,并移除空白。

您可能希望使用文本单位“em”(相对字体大小)而不是“sp”(缩放像素)来调整 lineHeight,以提高精度。有关选择适当文本单位的更多信息,请参阅 TextUnit

Image showing lineHeight as a measurement based on the lines directly above and below it.
图 1. 使用对齐和修剪来调整 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.AlignmentLineHeightStyle.TrimincludeFontPadding 必须设置为 false 才能使 Trim 工作)。对齐和修剪使用文本行之间的测量空间,以更适当地将其分配给所有行——包括单行文本和文本块的顶行。

LineHeightStyle.Alignment 定义了如何在行高提供的空间中对齐行。在每一行中,您可以将文本对齐到顶部、底部、居中或按比例对齐。LineHeightStyle.Trim 然后允许您保留或删除文本第一行顶部和最后一行底部的额外空间,这些空间是由于任何 lineHeight 和对齐调整而产生的。以下示例显示了当对齐居中时(LineHeightStyle.Alignment.Center),多行文本在各种 LineHeightStyle.Trim 配置下的外观。

An image demonstrating LineHeightStyle.Trim.None An image demonstrating LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
An image demonstrating LineHeightStyle.Trim.FirstLineTop An image demonstrating LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

请参阅修复 Compose 文本中的字体内边距博客文章,了解此更改的背景、includeFontPadding 在 View 系统中的工作方式,以及为 Compose 和新的 LineHeightStyle API 所做的更改。

插入换行符

LineBreak API 定义了文本在多行之间拆分的标准。您可以在 Text 可组合项的 TextStyle 块中指定所需的换行类型。预设的换行类型包括以下内容

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

以下代码片段使用 SimpleParagraph 来指定长文本块的换行行为

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
                )
            )
        }
    )
)

A text block that shows a simple line breaking strategy versus a text
  block with a paragraph-optimized breaking strategy. The text block with the simple
line breaking strategy has more variability in line lengths.
图 1. 采用简单换行策略的文本块(上)与采用段落优化换行的文本块(下)。

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

自定义换行

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

  • Balanced — 尝试平衡文本的行长,如果启用,还会应用自动连字符。建议用于小屏幕,如手表,以最大化显示的文本量。
  • HighQuality — 优化段落以获得更具可读性的文本,如果启用,包括连字符。(除了 BalancedSimple 之外,应作为所有内容的默认值。)
  • 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
            )
        }
    )
)

A paragraph with a balanced line breaking strategy and a paragraph
  formatted without a strategy. The paragraph with the balanced line breaking
  strategy has more consistent line lengths than the default.
图 2. 使用 Balanced 换行策略格式化的段落(上)与未采用换行策略格式化的段落。

CJK 注意事项

您还可以使用 StrictnessWordBreak API 自定义 LineBreak,这些 API 是专为 CJK 语言设计的。您可能不会总是在非 CJK 语言中看到这些 API 的效果。总的来说,换行规则是根据区域设置定义的。

Strictness 描述了换行的严格性,具有以下属性

  • Default — 区域设置的默认换行规则。可能对应于 NormalStrict
  • 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 = customTitleLineBreak
    )
)

Japanese text with Strictness and WordBreak settings versus default text.
图 3. 使用 StrictnessWordBreak 设置格式化的文本(上)与仅使用 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
                )
            )
        }
    )
)

A paragraph without hyphenation enabled and a paragraph with hyphenation enabled.
  When hyphenation is enabled, a word is hyphenated and split across two lines.
图 4. 未启用连字符的段落(上)与启用连字符的段落(下)。

启用后,连字符仅在以下条件下发生

  • 一个单词不适合一行。如果您使用 Simple 换行策略,则只有当一行比单个单词短时,单词才会出现连字符。
  • 设备上设置了适当的区域设置,因为适当的连字符是使用系统上存在的字典确定的。