Animar a aparência do texto caractere por caractere

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

Resultados

Figura 1. Texto e emoji animados caractere por caractere.

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 revelado. O texto exibido é atualizado dinamicamente para mostrar apenas os caracteres até o índice atual. Por fim, a variável executa a animação quando 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 sobre os caracteres, independentemente de como eles são armazenados. Por exemplo, emojis animados são compostos por vários caracteres. O BreakIterator garante que eles sejam tratados 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.

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 do Android:

O texto é uma parte central de qualquer interface. Descubra diferentes maneiras de apresentar texto no seu app para proporcionar 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 quer dar feedback?

Acesse nossa página de perguntas frequentes e saiba mais sobre os guias rápidos ou entre em contato e conte sua opinião.