样式段落

此页面介绍如何为段落设置文本样式。要设置段落级样式,您可以配置诸如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无论使用何种字母表都将对齐到右侧。

在段落中添加多个样式

要在段落中添加多个样式,您可以使用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 换行策略,则只有当一行短于单个单词时,才会对该单词进行连字符处理。
  • 您的设备上设置了相应的区域设置,因为适当的连字符处理是使用系统上存在的词典确定的。