Texto no Compose

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

Palavras "Hello World" em texto preto simples

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

Palavras "Hello World" em texto azul

Como mudar o tamanho do texto

@Composable
fun BigText() {
  Text("Hello World", fontSize = 30.sp)
}

Palavras "Hello World" em tamanho maior

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

Palavras "Hello World" em itálico

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

Palavras "Hello World" em negrito

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

Palavras "Hello World" centralizadas no elemento contêiner

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

As palavras "Hello World" com uma sombra azul

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

Palavras "Hello World" em duas fontes diferentes, com e sem serifas

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

Palavras "Hello World" em vários tipos de peso e estilo diferentes

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 de SpanStyleRange, equivalente ao estilo inline com intervalo de posições dentro do valor de texto
  • uma List de ParagraphStyleRange, 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")
        }
    )
}

Palavras "Hello World" com várias mudanças de estilo inline. A letra H está em azul e a letra W está em vermelho e negrito

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

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

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

Trecho de texto longo truncado após duas linhas

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

Trecho de texto longo truncado após duas linhas, com uma elipse no final

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.

Imagem mostrando lineHeight como uma medida baseada nas linhas diretamente acima e abaixo dela.
Use "Alignment" e "Trim" para ajustar o texto no conjunto "lineHeight" e corte o espaço extra, se houver.
@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).

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.

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

Pequeno trecho de texto selecionado pelo usuário.

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

Trecho de texto mais longo. O usuário tentou selecionar a passagem inteira, mas, como duas linhas tinham a opção "DisableSelection" aplicada, elas não foram selecionadas.

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:

  1. 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):
    • O estilo padrão é sólido
    • OutlinedTextField é a versão de estilo delineado.
  2. 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") }
    )
}

Campo de texto editável contendo a palavra "Hello". O campo tem o marcador não editável "label".

@Composable
fun SimpleOutlinedTextFieldSample() {
    var text by remember { mutableStateOf("") }

    OutlinedTextField(
        value = text,
        onValueChange = { text = it },
        label = { Text("Label") }
    )
}

Campo de texto editável com borda e marcador roxos.

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

Um TextField multilinha, com duas linhas editáveis e um marcador

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

Campo de entrada de senha com o texto mascarado.

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:

  1. 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")
    }
  2. 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.
    Você precisa adicionar a anotação ExperimentalTextApi para poder usar APIs de fontes para download no seu app.
  3. 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, usando FontWeight e FontStyle, 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)
    )
    
  4. Configure a FontFamily que você quer usar na função de composição Text e pronto.
    Text(
        fontFamily = fontFamily,
        text = "Hello World!"
    )
    
    Você também pode definir a tipografia para usar a 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.