Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
Możesz animować tekst, literę po literze, tak aby wyglądał jak strumień tekstu, podobny do tego, który wytwarza maszyna do pisania.
Zgodność wersji
Ta implementacja wymaga, aby minimalna wersja pakietu SDK projektu była ustawiona na poziom API 21 lub wyższy.
Zależności
Animowanie tekstu znak po znaku
Ten kod animuje tekst znak po znaku. Śledzenie indeksu pozwala kontrolować, ile tekstu jest widoczne. Wyświetlany tekst jest aktualizowany dynamicznie, aby wyświetlać tylko znaki do bieżącego indeksu. Na koniec zmienna uruchamia animację, gdy się zmieni.
@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 poprawnie iteruje po znakach niezależnie od tego, jak są przechowywane. Na przykład animowane emotikony składają się z wielu znaków. Opcja BreakIterator sprawia, że są one traktowane jako pojedynczy znak, dzięki czemu animacja nie jest przerywana.
LaunchedEffect uruchamia coroutine, aby wprowadzić opóźnienie między znakami. Aby wywołać animację, możesz zastąpić blok kodu listenerem kliknięcia lub dowolnym innym zdarzeniem.
Komponent Text jest ponownie renderowany za każdym razem, gdy wartość substringText ulegnie zmianie.
Wyniki
Rysunek 1. Tekst i emotikony animowane znak po znaku.
Kolekcje zawierające ten przewodnik
Ten przewodnik należy do tych kolekcji krótkich przewodników, które obejmują szersze zagadnienia związane z tworzeniem aplikacji na Androida:
Tekst wyświetlany
Tekst jest centralnym elementem każdego interfejsu użytkownika. Dowiedz się, jak możesz wyświetlać tekst w aplikacji, aby zapewnić użytkownikom przyjemne wrażenia.
Treść strony i umieszczone na niej fragmenty kodu podlegają licencjom opisanym w Licencji na treści. Java i OpenJDK są znakami towarowymi lub zastrzeżonymi znakami towarowymi należącymi do firmy Oracle lub jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2025-02-06 UTC.
[null,null,["Ostatnia aktualizacja: 2025-02-06 UTC."],[],[],null,["\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\nThis implementation requires that your project minSDK be set to API level 21 or\nhigher.\n\nDependencies\n\nAnimate text character-by-character\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/7a0ebbee11495f628cf9d574f6b6069c2867232a/compose/snippets/src/main/java/com/example/compose/snippets/animations/AnimationSnippets.kt#L939-L970\n```\n\n\u003cbr /\u003e\n\nKey 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\u003cbr /\u003e\n\n**Figure 1.** Text and emoji animated character-by-character.\n\n\u003cbr /\u003e\n\nCollections that contain this guide\n\nThis guide is part of these curated Quick Guide collections that cover\nbroader Android development goals: \n\nDisplay text \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\nCompose basics (video collection) \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 \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)"]]