Estilo do parágrafo

Esta página descreve como estilizar o texto do parágrafo. Para definir o estilo no nível do parágrafo, é possível configurar parâmetros como textAlign e lineHeight ou definir seu próprio ParagraphStyle.

Definir o alinhamento do texto

O parâmetro textAlign permite definir o alinhamento horizontal do texto em uma área de superfície combinável Text.

Por padrão, o Text seleciona o alinhamento natural do texto, dependendo do valor do conteúdo:

  • Borda esquerda do contêiner Text para alfabetos que seguem o sentido da esquerda para a direita, como latino, cirílico ou hangul
  • Borda direita do contêiner Text para alfabetos que seguem o sentido da direita para a esquerda, como árabe ou hebraico

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

As palavras

Se você quiser definir manualmente o alinhamento do texto de um elemento combinável Text, use TextAlign.Start e TextAlign.End em vez de TextAlign.Left e TextAlign.Right, respectivamente, porque eles se referem à borda correta do Text, dependendo da orientação do idioma preferencial. Por exemplo, TextAlign.End fica alinhado à direita para textos em francês e à esquerda para textos em árabe, mas TextAlign.Right alinha o texto à direita independente do alfabeto usado.

Adicionar vários estilos em um parágrafo

Para adicionar vários estilos em um parágrafo, use ParagraphStyle em um AnnotatedString, que pode receber anotações de estilo arbitrárias. Depois que uma parte do texto é marcada com um ParagraphStyle, ela fica separada do restante, como se tivesse um feed de linha no início e no fim.

Para mais informações sobre como adicionar vários estilos em um texto, consulte Adicionar vários estilos em um texto.

A AnnotatedString tem um builder de tipo seguro (link em inglês) para facilitar a criação: buildAnnotatedString. O snippet a seguir usa buildAnnotatedString para definir 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")
            }
        }
    )
}

Três parágrafos com três estilos diferentes: azul, vermelho e negrito e preto simples

Ajustar a altura da linha e o padding

includeFontPadding é uma propriedade legada que adiciona padding extra com base nas métricas de fonte na parte de cima da primeira linha e na parte de baixo da última linha de um texto. A partir da versão 2024.01.01 da BOM do Compose, o includeFontPadding é definido como false por padrão, o que alinha o layout de texto padrão com ferramentas de design comuns.

A capacidade de configurar a lineHeight não é nova e está disponível desde o Android Q. É possível configurar lineHeight para Text usando o parâmetro lineHeight, que distribui a altura da linha em cada linha do texto. Em seguida, é possível usar a nova LineHeightStyle API para configurar melhor como o texto é alinhado no espaço e remover espaços em branco.

Para melhorar a precisão, ajuste lineHeight usando a unidade "em" (tamanho relativo da fonte) em vez de "sp" (pixels dimensionados). Para mais informações sobre como selecionar uma unidade de texto adequada, consulte TextUnit.

Imagem mostrando lineHeight como uma medida baseada nas linhas diretamente acima e abaixo dela.
Figura 1. Use "Alignment" e "Trim" para ajustar o texto no conjunto lineHeight e corte o espaço extra, se necessário.

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

Além de ajustar lineHeight, agora você pode centralizar e personalizar ainda mais o texto usando configurações com a API experimental LineHeightStyle: LineHeightStyle.Alignment e LineHeightStyle.Trim. includeFontPadding precisa ser definida como false para que a opção "Trim" funcione. "Alignment" e "Trim" usam o espaço medido entre linhas de texto para distribuí-lo de maneira mais adequada para todas as linhas, incluindo uma única linha de texto e a linha na parte de cima de um bloco de texto.

LineHeightStyle.Alignment define como alinhar a linha no espaço fornecido pela altura da linha. Em cada linha, é possível alinhar o texto à parte de cima, de baixo, no centro ou proporcionalmente. LineHeightStyle.Trim permite que você deixe ou remova o espaço extra na parte de cima da primeira linha e na parte de baixo da última linha do texto, gerado usando qualquer ajuste de lineHeight e alinhamento. Os exemplos a seguir mostram a aparência de um texto de várias linhas com várias configurações de LineHeightStyle.Trim quando o alinhamento é centralizado (LineHeightStyle.Alignment.Center).

Uma imagem demonstrando LineHeightStyle.Trim.None. Uma imagem demonstrando LineHeightStyle.Trim.Both.
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Uma imagem demonstrando LineHeightStyle.Trim.FirstLineTop. Uma imagem demonstrando LineHeightStyle.Trim.LastLineBottom.
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Consulte a postagem do blog Como corrigir o padding da fonte do texto no Compose (em inglês) para saber mais sobre o contexto dessa mudança, como includeFontPadding funcionava no sistema de visualização e as mudanças feitas no Compose e nas novas APIs LineHeightStyle.

Inserir quebras de linha

A API LineBreak define os critérios de divisão do texto em várias linhas. É possível especificar o tipo de quebra de linha que você quer no bloco TextStyle do elemento combinável Text. Os tipos de quebra de linha predefinidos incluem o seguinte:

  • Simple: quebra de linha rápida e básica. Recomendado para campos de entrada de texto.
  • Heading: quebra de linha com regras mais flexíveis. Recomendado para textos curtos, como títulos.
  • Paragraph: quebra de linha mais lenta e de melhor qualidade para melhorar a legibilidade. Recomendado para quantidades maiores de texto, como parágrafos.

O snippet a seguir usa Simple e Paragraph para especificar o comportamento de quebra de linha em um bloco longo de texto:

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

Um bloco de texto que mostra uma estratégia simples de quebra de linha em comparação com um bloco
  de texto com uma estratégia de quebra otimizada para parágrafos. O bloco de texto com a estratégia simples
de quebra de linha tem mais variabilidade nos comprimentos de linha.
Figura 1. Um bloco de texto com uma estratégia simples de quebra de linha (parte de cima) em comparação com um bloco de texto com quebra de linha otimizada para parágrafos (parte de baixo).

Na saída acima, observe que o comportamento de quebra de linha Paragraph produz um resultado visualmente mais equilibrado do que a quebra de linha Simple.

Personalizar quebras de linha

Também é possível criar sua própria configuração de LineBreak com o parâmetro Strategy. O Strategy pode ser:

  • Balanced: tenta equilibrar os comprimentos de linha do texto, aplicando também a separação silábica automática, se ativada. Recomendado para telas pequenas, como relógios, para maximizar a quantidade de texto exibido.
  • HighQuality: otimiza um parágrafo para um texto mais legível, incluindo a quebra de palavras, se ativada. Deve ser o padrão para tudo que não é Balanced ou Simple.
  • Simple: estratégia básica e rápida. Se ativado, a divisão silábica é feita apenas para palavras que não cabem em uma linha inteira sozinhas. Útil para editar texto e evitar mudanças de posição ao digitar.

O snippet a seguir mostra a diferença entre um parágrafo com configurações padrão e um parágrafo otimizado para telas pequenas com a estratégia de quebra de linha 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
            )
        }
    )
)

Um parágrafo com uma estratégia de quebra de linha equilibrada e um parágrafo
  formatado sem uma estratégia. O parágrafo com a estratégia de quebra de linha equilibrada
  tem comprimentos de linha mais consistentes do que o padrão.
Figura 2. Um parágrafo formatado com uma estratégia de quebra de linha Balanced (parte de cima) em comparação com um parágrafo formatado sem uma estratégia de quebra de linha.

Considerações sobre CJK

Também é possível personalizar LineBreak com as APIs Strictness e WordBreak, que foram projetadas especificamente para idiomas CJK. Talvez você não veja os efeitos dessas APIs em idiomas que não sejam CJK. No geral, as regras de quebra de linha são definidas com base na localidade.

Strictness descreve a rigidez do corte de linha com as seguintes propriedades:

  • Default: regras de quebra padrão para a localidade. Pode corresponder a Normal ou Strict.
  • Loose: as regras menos restritivas. Adequado para linhas curtas.
  • Normal: as regras mais comuns para quebra de linha.
  • Strict: as regras mais rigorosas para quebra de linha.

WordBreak define como os quebras de linha devem ser inseridos nas palavras com as seguintes propriedades:

  • Default: regras de quebra padrão para a localidade.
  • Phrase: a quebra de linha é baseada em frases.

O snippet a seguir usa um nível de exigência Strict e uma configuração de divisão de palavras Phrase para um texto em japonês:

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

Texto em japonês com as configurações "Strictness" e "WordBreak" em comparação com o texto padrão.
Figura 3. Texto formatado com as configurações Strictness e WordBreak (parte de cima) em comparação com o texto formatado apenas com LineBreak.Heading (parte de baixo).

Usar hífen para dividir o texto em linhas

A API Hyphens permite adicionar suporte a hifenização ao app. Hifenização se refere à inserção de um sinal de pontuação semelhante a um traço para indicar que uma palavra está dividida entre linhas de texto. Quando ativado, a divisão silábica é adicionada entre as sílabas de uma palavra nos pontos de divisão apropriados.

Por padrão, a divisão de palavras não está ativada. Para ativar a divisão silábica, adicione Hyphens.Auto como um parâmetro em um bloco TextStyle:

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

Um parágrafo sem divisão silábica ativada e outro com a divisão ativada.
  Quando a divisão silábica está ativada, uma palavra é dividida em duas linhas.
Figura 4. Um parágrafo sem a quebra de hifenização ativada (acima) e outro com a quebra de hifenização ativada (abaixo).

Quando ativada, a divisão silábica só ocorre nas seguintes condições:

  • Uma palavra não cabe em uma linha. Se você usar uma estratégia de quebra de linha Simple, a divisão de uma palavra vai ocorrer apenas se uma linha for mais curta que a palavra.
  • A localidade apropriada é definida no dispositivo, já que a divisão silábica adequada é determinada usando os dicionários presentes no sistema.