逐字符为文本添加动画效果

您可以逐个字符为文本添加动画效果,使其看起来像是打字机输入的流式文本。

版本兼容性

此实现要求将项目 minSDK 设置为 API 级别 21 或更高级别。

依赖项

逐字逐句为文本添加动画效果

这段代码会逐字符为文本添加动画效果。它会跟踪一个索引,以控制显示的文本量。显示的文本会动态更新,以仅显示当前索引之前的字符。最后,该变量会在发生变化时运行动画。

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

代码要点

  • 无论字符的存储方式如何,BreakIterator 都会正确迭代字符。例如,动画表情符号由多个字符组成;BreakIterator 会确保将它们作为单个字符进行处理,以免动画中断。
  • LaunchedEffect 会启动一个协程,以在字符之间引入延迟。您可以将代码块替换为点击监听器或任何其他事件,以触发动画。
  • 每次更新 substringText 的值时,Text 可组合项都会重新渲染。

结果

图 1. 文本和表情符号逐个字符动画效果。

包含本指南的集合

本指南属于以下精选快速入门集合,这些集合涵盖了更广泛的 Android 开发目标:

文字对任何界面都属于核心内容。了解在应用中呈现文本的不同方式,以提供愉悦的用户体验。
本系列视频介绍了各种 Compose API,可让您快速了解可用 API 以及如何使用它们。

有问题或反馈

请访问我们的常见问题解答页面,了解简短指南,或与我们联系,告诉我们您的想法。