O texto é uma peça central de qualquer IU, e o Jetpack Compose facilita a exibição ou criação de textos. O Compose usa a composição de elementos básicos, ou seja, não é necessário substituir propriedades e métodos ou estender grandes classes para fazer com que um design e uma lógica de composição funcionem da forma que você quer.
Como base, o Compose fornece um BasicText
e um BasicTextField
, que são as
estruturas básicas para exibir o texto e processar a entrada do usuário. Em um nível mais alto, o Compose
fornece o Text
e o TextField
,
que são elementos combináveis que seguem as diretrizes do Material Design. É recomendável
usar esses elementos porque eles têm uma aparência familiar aos usuários do Android e incluem
outras opções para simplificar a personalização sem precisar de muita programação.
Como exibir texto
A forma mais básica de exibir textos é usando o elemento combinávelText
com uma
String
como argumento:
@Composable
fun SimpleText() {
Text("Hello World")
}
Exibir texto do recurso
Recomendamos que você use recursos de string
em vez de valores de Text
fixos no código. Dessa forma, é possível compartilhar as mesmas strings com as
visualizações do Android e preparar o app para internacionalização:
@Composable
fun StringResourceText() {
Text(stringResource(R.string.hello_world))
}
Como definir o estilo do texto
O elemento combinável Text
tem vários parâmetros opcionais para definir o estilo do conteúdo.
Veja abaixo uma lista dos parâmetros que abrangem os casos de uso mais comuns relacionados a textos. Para
ver todos os parâmetros de Text
, recomendamos que você consulte o código-fonte
do texto
do Compose (em inglês).
Sempre que você definir um desses parâmetros, o mesmo estilo será aplicado a todo o valor do texto. Caso seja necessário aplicar vários estilos na mesma linha ou parágrafo, consulte a seção sobre vários estilos inline.
Como mudar a cor do texto
@Composable
fun BlueText() {
Text("Hello World", color = Color.Blue)
}
Como mudar o tamanho do texto
@Composable
fun BigText() {
Text("Hello World", fontSize = 30.sp)
}
Como deixar o texto em itálico
Use o parâmetro fontStyle
para aplicar itálico ao texto ou defina outro
FontStyle
.
@Composable
fun ItalicText() {
Text("Hello World", fontStyle = FontStyle.Italic)
}
Como deixar o texto em negrito
Use o parâmetro fontWeight
para aplicar negrito ao texto ou defina outro FontWeight
.
@Composable
fun BoldText() {
Text("Hello World", fontWeight = FontWeight.Bold)
}
Alinhamentos de texto
O parâmetro textAlign
permite definir o alinhamento do texto em uma
área de superfície do elemento 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
@Preview(showBackground = true)
@Composable
fun CenterText() {
Text("Hello World", textAlign = TextAlign.Center,
modifier = Modifier.width(150.dp))
}
Caso você queira 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.
Sombra
O parâmetro style
permite definir um objeto do tipo TextStyle
e configurar vários parâmetros, como uma sombra.
Shadow
recebe uma cor
para a sombra, o deslocamento ou a localização em relação ao Text
e
ao raio de desfoque, que é a intensidade do efeito desfocado.
@Preview(showBackground = true)
@Composable
fun TextShadow() {
val offset = Offset(5.0f, 10.0f)
Text(
text = "Hello world!",
style = TextStyle(
fontSize = 24.sp,
shadow = Shadow(
color = Color.Blue,
offset = offset,
blurRadius = 3f
)
)
)
}
Como trabalhar com fontes
Text
tem um parâmetro fontFamily
para permitir a configuração da fonte usada no
elemento combinável. Por padrão, as famílias de fontes Serif, Sans Serif, fontes monoespaçadas e cursivas
estão incluídas:
@Composable
fun DifferentFonts() {
Column {
Text("Hello World", fontFamily = FontFamily.Serif)
Text("Hello World", fontFamily = FontFamily.SansSerif)
}
}
É possível usar o atributo fontFamily
para trabalhar com fontes personalizadas,
definidas na pasta res/font
:
font" do ambiente de desenvolvimento" class="l10n-absolute-url-src screenshot" l10n-attrs-original-order="src,alt,width,class" src="https://developer.android.com/static/images/jetpack/compose/text-font-folder.png" width="400" />
O exemplo abaixo mostra como definir uma fontFamily
com base nesses arquivos de
fonte e como usar a função Font
:
val firaSansFamily = FontFamily(
Font(R.font.firasans_light, FontWeight.Light),
Font(R.font.firasans_regular, FontWeight.Normal),
Font(R.font.firasans_italic, FontWeight.Normal, FontStyle.Italic),
Font(R.font.firasans_medium, FontWeight.Medium),
Font(R.font.firasans_bold, FontWeight.Bold)
)
Por fim, você pode transmitir essa fontFamily
para o elemento combinável Text
. Como uma
fontFamily
pode incluir pesos diferentes, é possível definir o fontWeight
manualmente para
selecionar o peso certo para o texto:
Column {
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Light)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Normal)
Text(
..., fontFamily = firaSansFamily, fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Italic
)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Medium)
Text(..., fontFamily = firaSansFamily, fontWeight = FontWeight.Bold)
}
Para aprender a definir a tipografia no app todo, consulte a documentação sobre temas.
Vários estilos em um texto
Para definir estilos diferentes no mesmo elemento combinável Text
,
use uma AnnotatedString
,
uma string que pode receber anotações de estilo arbitrárias.
AnnotatedString
é uma classe de dados que contém:
- Um valor
Text
- Uma
List
deSpanStyleRange
, equivalente ao estilo inline com intervalo de posições dentro do valor de texto - uma
List
deParagraphStyleRange
, especificando o alinhamento, a direção, a altura da linha e o estilo de recuo do texto.
O TextStyle
é usado
no elemento combinável Text
, ao passo que o SpanStyle
e o ParagraphStyle
são usados na AnnotatedString
.
A diferença entre SpanStyle
e ParagraphStyle
é que ParagraphStyle
pode ser aplicado a um parágrafo inteiro, ao passo que SpanStyle
pode ser aplicado no
nível do caractere. 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.
A AnnotatedString
tem um builder de tipo
seguro (em inglês)
para facilitar a criação: buildAnnotatedString
.
@Composable
fun MultipleStylesInText() {
Text(
buildAnnotatedString {
withStyle(style = SpanStyle(color = Color.Blue)) {
append("H")
}
append("ello ")
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold, color = Color.Red)) {
append("W")
}
append("orld")
}
)
}
Podemos definir o ParagraphStyle
da mesma maneira:
@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")
}
}
)
}
Número máximo de linhas
Para limitar o número de linhas visíveis em um elemento combinável Text
, defina o parâmetro
maxLines
:
@Composable
fun LongText() {
Text("hello ".repeat(50), maxLines = 2)
}
Excesso de texto
Ao limitar um texto longo, é recomendável indicar um TextOverflow
,
que só vai ser exibido se o texto na tela for truncado. Para fazer isso, defina o parâmetro
textOverflow
:
@Composable
fun OverflowedText() {
Text("Hello Compose ".repeat(50), maxLines = 2, overflow = TextOverflow.Ellipsis)
}
APIs includeFontPadding e lineHeight
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.
No Compose 1.2.0, a API includeFontPadding está definida como verdadeira por padrão.
Agora, recomendamos definir includeFontPadding
como falsa (que remove o
padding extra) usando a API descontinuada PlatformTextStyle
do
Compose 1.2.0 e ajustar o texto.
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). Veja mais detalhes sobre
como selecionar uma unidade de medida adequada para textos neste link.

@Composable
fun AlignedText() {
Text(
text = myText,
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 falsa 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
).
![]() |
![]() |
LineHeightStyle.Trim.None | LineHeightStyle.Trim.Both |
![]() |
![]() |
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
.
Temas
Para usar o tema do app para definir o estilo de texto, consulte a documentação sobre temas.
Interações do usuário
O Jetpack Compose permite interatividade detalhada no Text
. A seleção de texto agora
é mais flexível e pode ser feita em layouts de composição. As interações do usuário
nos textos são diferentes de outros layouts do mesmo tipo, já que não é possível adicionar um modificador
a uma parte de um elemento Text
. Esta seção destaca as diferentes APIs
para permitir interações do usuário.
Como selecionar texto
Por padrão, os elementos de composição não são selecionáveis, ou seja, os usuários não
podem selecionar e copiar textos do app. Para ativar a seleção de texto, é necessário unir
os elementos de texto com um elemento combinável SelectionContainer
:
@Composable
fun SelectableText() {
SelectionContainer {
Text("This text is selectable")
}
}
Você pode desativar a seleção de texto em partes específicas de uma área selecionável. Para
fazer isso, é necessário unir a parte que não pode ser selecionada a um elemento combinável
DisableSelection
:
@Composable
fun PartiallySelectableText() {
SelectionContainer {
Column {
Text("This text is selectable")
Text("This one too")
Text("This one as well")
DisableSelection {
Text("But not this one")
Text("Neither this one")
}
Text("But again, you can select this one")
Text("And this one too")
}
}
}
Como descobrir a posição de um clique no texto
Para detectar cliques no Text
, adicione o modificador
clickable
. No entanto, se você quiser descobrir a posição de um clique em um
elemento combinável Text
, como no caso em que há ações diferentes baseadas em
partes distintas do texto, use um
ClickableText
:
@Composable
fun SimpleClickableText() {
ClickableText(
text = AnnotatedString("Click Me"),
onClick = { offset ->
Log.d("ClickableText", "$offset -th character is clicked.")
}
)
}
Clique com anotação
Quando um usuário clica em um elemento combinável Text
, você pode anexar mais
informações a uma parte do valor do Text
, como um URL anexado a uma palavra específica
que é aberto em um navegador. Para fazer isso, anexe uma
anotação, que usa uma tag (String
), um item (String
) e um intervalo de texto
como parâmetros. A partir de uma AnnotatedString
, essas anotações podem ser filtradas
de acordo com as tags ou intervalos de texto. Veja um exemplo:
@Composable
fun AnnotatedClickableText() {
val annotatedText = buildAnnotatedString {
append("Click ")
// We attach this *URL* annotation to the following content
// until `pop()` is called
pushStringAnnotation(tag = "URL",
annotation = "https://developer.android.com")
withStyle(style = SpanStyle(color = Color.Blue,
fontWeight = FontWeight.Bold)) {
append("here")
}
pop()
}
ClickableText(
text = annotatedText,
onClick = { offset ->
// We check if there is an *URL* annotation attached to the text
// at the clicked position
annotatedText.getStringAnnotations(tag = "URL", start = offset,
end = offset)
.firstOrNull()?.let { annotation ->
// If yes, we log its value
Log.d("Clicked URL", annotation.item)
}
}
)
}
Como inserir e modificar texto
TextField
permite que os usuários insiram e modifiquem o texto. Há dois níveis de
implementações de TextField
:
TextField
é a implementação do Material Design. Recomendamos que você escolha essa implementação, que segue as diretrizes do Material Design (link em inglês):- A função
BasicTextField
permite que os usuários editem o texto usando o teclado de software ou hardware, mas não oferece decorações como dicas ou marcadores de posição.
@Composable
fun SimpleFilledTextFieldSample() {
var text by remember { mutableStateOf("Hello") }
TextField(
value = text,
onValueChange = { text = it },
label = { Text("Label") }
)
}
@Composable
fun SimpleOutlinedTextFieldSample() {
var text by remember { mutableStateOf("") }
OutlinedTextField(
value = text,
onValueChange = { text = it },
label = { Text("Label") }
)
}
Como definir o estilo de TextField
TextField
e BasicTextField
têm vários parâmetros em comum
para personalização. A lista completa do TextField
está disponível no código-fonte
do TextField
(em inglês).
Veja uma lista não exaustiva de alguns parâmetros úteis:
singleLine
maxLines
textStyle
@Composable
fun StyledTextField() {
var value by remember { mutableStateOf("Hello\nWorld\nInvisible") }
TextField(
value = value,
onValueChange = { value = it },
label = { Text("Enter text") },
maxLines = 2,
textStyle = TextStyle(color = Color.Blue, fontWeight = FontWeight.Bold),
modifier = Modifier.padding(20.dp)
)
}
Recomendamos o uso de TextField
em vez de BasicTextField
quando o design chama um
TextFieldField ou OutlineTextField do Material Design. No entanto, use BasicTextField
ao criar designs que não precisam das decorações da especificação do Material Design.
Opções do teclado
O TextField
permite definir opções de configuração do teclado, como o layout
dele, ou ativar a correção automática, caso haja suporte. Algumas
opções podem não ser garantidas se o teclado de software não estiver de acordo com as
opções apresentadas aqui. Veja a lista de opções de teclado
com suporte:
capitalization
autoCorrect
keyboardType
imeAction
Formatação
O TextField
permite definir uma VisualTransformation
no valor de entrada, como substituir caracteres por *
para senhas ou
inserir hifens a cada quatro (4) dígitos em número de cartão de crédito:
@Composable
fun PasswordTextField() {
var password by rememberSaveable { mutableStateOf("") }
TextField(
value = password,
onValueChange = { password = it },
label = { Text("Enter password") },
visualTransformation = PasswordVisualTransformation(),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password)
)
}
Mais exemplos estão disponíveis no código-fonte de VisualTransformSamples.
Como limpar entradas
Uma tarefa comum ao editar o texto é remover os caracteres iniciais ou transformar a string de entrada sempre que ela mudar.
Como modelo, suponha que o teclado possa fazer edições grandes e arbitrárias
em cada onValueChange
. Isso pode acontecer, por exemplo, se o usuário usar a
correção automática, substituir uma palavra por um emoji ou usar outros recursos de edição inteligentes. Para
processar a ação corretamente, programe qualquer lógica de transformação com o pressuposto de que
o texto atual transmitido para o método onValueChange
não está relacionado aos valores anteriores ou aos próximos
que vão ser transmitidos para onValueChange
.
Para implementar um campo de texto que não aceita zeros à esquerda, remova todos esses zeros sempre que o valor mudar.
@Composable
fun NoLeadingZeroes() {
var input by rememberSaveable { mutableStateOf("") }
TextField(
value = input,
onValueChange = { newText ->
input = newText.trimStart { it == '0' }
}
)
}
Para controlar a posição do cursor ao limpar o texto, use a sobrecarga TextFieldValue
da função TextField
como parte do estado.
Fontes para download
Do Compose 1.2-alpha07 em diante, é possível usar a API de fontes para download no app Compose para fazer o download de fontes do Google de forma assíncrona e as usar no seu app.
No momento, não há suporte às fontes para download fornecidas por provedores personalizados.
Como usar as fontes para download de forma programática
Para fazer o download de uma fonte de forma programática no seu app, siga estas etapas:
- Adicione a dependência:
Groovy
dependencies { ... implementation "androidx.compose.ui:ui-text-google-fonts:1.3.0" }
Kotlin
dependencies { ... implementation("androidx.compose.ui:ui-text-google-fonts:1.3.0") }
- Inicialize a classe
GoogleFont.Provider
com as credenciais da biblioteca Google Fonts.@OptIn(ExperimentalTextApi::class) val provider = GoogleFont.Provider( providerAuthority = "com.google.android.gms.fonts", providerPackage = "com.google.android.gms", certificates = R.array.com_google_android_gms_fonts_certs )
Os parâmetros que o provedor recebe são estes:- A autoridade de provedor de fontes para a biblioteca Google Fonts.
- O pacote de provedor de fontes para confirmar a identidade do provedor.
- Uma lista de conjuntos de hashes para que os certificados confirmem a identidade
do provedor. Você pode encontrar os hashes necessários para o provedor da biblioteca Google Fonts
no arquivo
font_certs.xml
(em inglês) do app de exemplo JetChat.
ExperimentalTextApi
para poder usar APIs de fontes para download no seu app. - Defina uma
FontFamily
da seguinte maneira:import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider) )
Você pode consultar outros parâmetros para sua fonte, como o peso e o estilo, usandoFontWeight
eFontStyle
, respectivamente:import androidx.compose.ui.text.googlefonts.GoogleFont import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold, style = FontStyle.Italic) )
- Configure a
FontFamily
que você quer usar na função de composição Text e pronto.Text( fontFamily = fontFamily, text = "Hello World!" )
FontFamily
.val MyTypography = Typography( body1 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Normal, fontSize = ... ), body2 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.Bold, letterSpacing = ... ), h4 = TextStyle( fontFamily = fontFamily, fontWeight = FontWeight.SemiBold ... ), ...
Em seguida, defina a tipografia para usar o tema do seu app:MyAppTheme( typography = MyTypography ) { ...
Para ver um exemplo de app que está implementando fontes para download no Compose com o Material3, confira o app de exemplo JetChat (em inglês).
Fontes substitutas
É possível determinar uma cadeia de fontes substitutas que vão ser usadas caso o download da fonte não seja concluído corretamente. Por exemplo, caso você tenha a fonte para download definida desta forma:
import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold) )
Você pode definir os padrões da fonte para os dois pesos:
import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.googlefonts.Font val fontName = GoogleFont("Lobster Two") val fontFamily = FontFamily( Font(googleFont = fontName, fontProvider = provider), Font(resId = R.font.my_font_regular), Font(googleFont = fontName, fontProvider = provider, weight = FontWeight.Bold), Font(resId = R.font.my_font_regular_bold, weight = FontWeight.Bold) )
Verifique se você está adicionando as importações corretas.
Essa definição cria uma FontFamily
contendo duas cadeias,
uma para cada peso. O mecanismo de carregamento primeiro vai tentar resolver a fonte on-line
e depois a localizada na pasta de recursos R.font
local.
Como depurar a implementação
Para verificar se o download da fonte está sendo feito corretamente, defina um gerenciador de corrotina de depuração. Ele fornece o comportamento do que fazer caso a fonte não carregue de forma assíncrona.
Comece criando uma interface
CoroutineExceptionHandler
(em inglês).
val handler = CoroutineExceptionHandler { _, throwable ->
// process the Throwable
Log.e(TAG, "There has been an issue: ", throwable)
}
Em seguida, ela precisa ser transmitida para o método
createFontFamilyResolver
para que o resolvedor o use o novo gerenciador:
CompositionLocalProvider(
LocalFontFamilyResolver provides createFontFamilyResolver(LocalContext.current, handler)
) {
Column {
Text(
text = "Hello World!",
style = MaterialTheme.typography.body1
)
}
}
Você também pode usar a API
isAvailableOnDevice
do provedor para testar se ele está disponível e se os certificados estão
configurados corretamente. Para fazer isso, chame o método isAvailableOnDevice
,
que vai retornar um valor falso se o provedor estiver configurado incorretamente.
val context = LocalContext.current
LaunchedEffect(Unit) {
if (provider.isAvailableOnDevice(context)) {
Log.d(TAG, "Success!")
}
}
Avisos
A biblioteca Google Fonts leva vários meses para disponibilizar novas fontes no Android.
Há um intervalo entre quando uma fonte é adicionada na página
fonts.google.com e o momento em que
ela é disponibilizada pela API de fontes para download no sistema de visualização ou
no Compose. As fontes recém-adicionadas podem não ser carregadas no seu app com uma
IllegalStateException
(em inglês).
Para ajudar os desenvolvedores a identificar esse erro em relação a outros tipos de erro de carregamento de fonte, adicionamos uma mensagem descritiva das mudanças
neste link sobre a exceção no Compose.