Animar a aparência do texto caractere por caractere

É possível animar, caractere por caractere, a aparência do texto para que ele pareça um efeito de digitação em streaming, semelhante ao que uma máquina de escrever produziria.

Compatibilidade de versões

Essa implementação exige que o minSDK do projeto seja definido como nível 21 da API ou mais recente.

Dependências

Animar texto caractere por caractere

Esse código anima o texto caractere por caractere. Ele rastreia um índice para controlar a quantidade de texto revelada. O texto exibido é atualizado dinamicamente para mostrar apenas os caracteres até o índice atual. Por fim, a variável executa a animação quando ela muda.

@Composable
private fun AnimatedText() {
    val text = "This text animates as though it is being typed \uD83E\uDDDE\u200D♀\uFE0F \uD83D\uDD10  \uD83D\uDC69\u200D❤\uFE0F\u200D\uD83D\uDC68 \uD83D\uDC74\uD83C\uDFFD"

    // Use BreakIterator as it correctly iterates over characters regardless of how they are
    // stored, for example, some emojis are made up of multiple characters.
    // You don't want to break up an emoji as it animates, so using BreakIterator will ensure
    // this is correctly handled!
    val breakIterator = remember(text) { BreakIterator.getCharacterInstance() }

    // Define how many milliseconds between each character should pause for. This will create the
    // illusion of an animation, as we delay the job after each character is iterated on.
    val typingDelayInMs = 50L

    var substringText by remember {
        mutableStateOf("")
    }
    LaunchedEffect(text) {
        // Initial start delay of the typing animation
        delay(1000)
        breakIterator.text = StringCharacterIterator(text)

        var nextIndex = breakIterator.next()
        // Iterate over the string, by index boundary
        while (nextIndex != BreakIterator.DONE) {
            substringText = text.subSequence(0, nextIndex).toString()
            // Go to the next logical character boundary
            nextIndex = breakIterator.next()
            delay(typingDelayInMs)
        }
    }
    Text(substringText)

Pontos principais sobre o código

  • BreakIterator itera corretamente os caracteres, independentemente de como eles são armazenados. Por exemplo, emojis animados são compostos por vários caracteres. BreakIterator garante que eles sejam processados como um único caractere, para que a animação não seja interrompida.
  • LaunchedEffect inicia uma corrotina para introduzir o atraso entre os caracteres. Você pode substituir o bloco de código por um listener de clique ou qualquer outro evento para acionar a animação.
  • O elemento combinável Text é renderizado novamente sempre que o valor de substringText é atualizado.

Resultados

Figura 1. Texto e emoji animados caractere por caractere.

Coleções que contêm este guia

Este guia faz parte destas coleções selecionadas de guias rápidos que abrangem metas mais amplas de desenvolvimento para Android:

O texto é uma peça central de qualquer interface. Descubra maneiras diferentes de apresentar texto no app para oferecer uma experiência agradável ao usuário.
Esta série de vídeos apresenta várias APIs do Compose, mostrando rapidamente o que está disponível e como usá-las.

Tem dúvidas ou feedback?

Acesse a página de perguntas frequentes e saiba mais sobre os guias rápidos ou entre em contato e conte o que você pensa.