Animar a aparência do texto caractere por caractere
Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
É 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.
@ComposableprivatefunAnimatedText(){valtext="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!valbreakIterator=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.valtypingDelayInMs=50LvarsubstringTextbyremember{mutableStateOf("")}LaunchedEffect(text){// Initial start delay of the typing animationdelay(1000)breakIterator.text=StringCharacterIterator(text)varnextIndex=breakIterator.next()// Iterate over the string, by index boundarywhile(nextIndex!=BreakIterator.DONE){substringText=text.subSequence(0,nextIndex).toString()// Go to the next logical character boundarynextIndex=breakIterator.next()delay(typingDelayInMs)}}Text(substringText)
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:
Texto de exibição
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.
O conteúdo e os exemplos de código nesta página estão sujeitos às licenças descritas na Licença de conteúdo. Java e OpenJDK são marcas registradas da Oracle e/ou suas afiliadas.
Última atualização 2025-02-06 UTC.
[null,null,["Última atualização 2025-02-06 UTC."],[],[],null,["# Animate character-by-character the appearance of text\n\n\u003cbr /\u003e\n\nYou can animate, character-by-character, the appearance of text, so it looks\nlike a streaming typing effect, similar to what a typewriter would produce.\n\nVersion compatibility\n---------------------\n\nThis implementation requires that your project minSDK be set to API level 21 or\nhigher.\n\n### Dependencies\n\n### Kotlin\n\n\u003cbr /\u003e\n\n```kotlin\n implementation(platform(\"androidx.compose:compose-bom:2025.08.00\"))\n implementation(\"androidx.compose.material3:material3\")\n \n```\n\n\u003cbr /\u003e\n\n### Groovy\n\n\u003cbr /\u003e\n\n```groovy\n implementation platform('androidx.compose:compose-bom:2025.08.00')\n implementation 'androidx.compose.material3:material3'\n \n```\n\n\u003cbr /\u003e\n\nAnimate text character-by-character\n-----------------------------------\n\nThis code animates text character-by-character. It tracks an index to control\nhow much of the text is revealed. The displayed text updates dynamically to show\nonly the characters up to the current index. Finally, the variable runs the\nanimation when it changes.\n\n\n```kotlin\n@Composable\nprivate fun AnimatedText() {\n 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\"\n\n // Use BreakIterator as it correctly iterates over characters regardless of how they are\n // stored, for example, some emojis are made up of multiple characters.\n // You don't want to break up an emoji as it animates, so using BreakIterator will ensure\n // this is correctly handled!\n val breakIterator = remember(text) { BreakIterator.getCharacterInstance() }\n\n // Define how many milliseconds between each character should pause for. This will create the\n // illusion of an animation, as we delay the job after each character is iterated on.\n val typingDelayInMs = 50L\n\n var substringText by remember {\n mutableStateOf(\"\")\n }\n LaunchedEffect(text) {\n // Initial start delay of the typing animation\n delay(1000)\n breakIterator.text = StringCharacterIterator(text)\n\n var nextIndex = breakIterator.next()\n // Iterate over the string, by index boundary\n while (nextIndex != BreakIterator.DONE) {\n substringText = text.subSequence(0, nextIndex).toString()\n // Go to the next logical character boundary\n nextIndex = breakIterator.next()\n delay(typingDelayInMs)\n }\n }\n Text(substringText)https://github.com/android/snippets/blob/dd30aee903e8c247786c064faab1a9ca8d10b46e/compose/snippets/src/main/java/com/example/compose/snippets/animations/AnimationSnippets.kt#L939-L970\n```\n\n\u003cbr /\u003e\n\n### Key points about the code\n\n- [`BreakIterator`](/reference/android/icu/text/BreakIterator) correctly iterates over characters regardless of how they are stored. For example, animated emojis are made up of multiple characters; `BreakIterator` ensures that they're handled as a single character, so that the animation isn't broken.\n- [`LaunchedEffect`](/reference/kotlin/androidx/compose/runtime/package-summary#LaunchedEffect(kotlin.Any,kotlin.coroutines.SuspendFunction1)) starts a coroutine to introduce the delay between the characters. You can replace the code block with a click listener--or any other event--to trigger animation.\n- The [`Text`](/reference/kotlin/androidx/compose/material/package-summary#Text(kotlin.String,androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.font.FontStyle,androidx.compose.ui.text.font.FontWeight,androidx.compose.ui.text.font.FontFamily,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextDecoration,androidx.compose.ui.text.style.TextAlign,androidx.compose.ui.unit.TextUnit,androidx.compose.ui.text.style.TextOverflow,kotlin.Boolean,kotlin.Int,kotlin.Int,kotlin.Function1,androidx.compose.ui.text.TextStyle)) composable re-renders every time the value of `substringText` is updated.\n\nResults\n-------\n\n\u003cbr /\u003e\n\n**Figure 1.** Text and emoji animated character-by-character.\n\n\u003cbr /\u003e\n\nCollections that contain this guide\n-----------------------------------\n\nThis guide is part of these curated Quick Guide collections that cover\nbroader Android development goals: \n\n### Display text\n\nText is a central piece of any UI. Find out different ways you can present text in your app to provide a delightful user experience. \n[Quick guide collection](/develop/ui/compose/quick-guides/collections/display-text) \n\n### Compose basics (video collection)\n\nThis series of videos introduces various Compose APIs, quickly showing you what's available and how to use them. \n[Quick guide collection](/develop/ui/compose/quick-guides/collections/compose-basics) \n\nHave questions or feedback\n--------------------------\n\nGo to our frequently asked questions page and learn about quick guides or reach out and let us know your thoughts. \n[Go to FAQ](/quick-guides/faq) [Leave feedback](https://issuetracker.google.com/issues/new?component=1573691&template=1993320)"]]