五分钟搞定 Compose 的打字机效果

这周一天中午吃饭,我同事问我,能不能用 Compose 模仿一下 AI 的那种打字效果。

我跟他说那个不是模仿出来的,一般大模型接口使用的是 SSE 的协议,这个数据一帧一帧的发送,效果上就是几个字,几个字那么吐出来的,你不是大模型的接口没必要搞这个效果啊!

他说,那如果我想假装我是大模型接口呢?

斯......

我懂你意思!

那我们,Let's go!

核心思路

首先,我们需要创建一个可复用的 Composable 函数 TextTypeWriter,该函数将负责承载打字机动画的核心逻辑。为了保证灵活性,我们设计以下参数:

  • text:需要展示的完整文本字符串;
  • modifier:修饰符,用于调整文本组件的布局、间距等属性,在 Compose 中,这个参数默认在第一位;
  • onDone:动画完成后的回调函数,可用于触发后续操作。

Let's Go

思路已经清晰,那么让我们开始编码吧!

1. 状态管理:存储文本

首先需要创建一个可变状态变量,用于存储当前已显示的文本内容。借助 Jetpack Compose 的 remember 和 mutableStateOf,可以确保状态在重组时保持持久化,且状态变化时会自动触发 UI 更新:

kotlin 复制代码
var textToDisplay by remember { mutableStateOf("") }

2. 动画触发:逐字追加

使用 LaunchedEffect 来启动动画逻辑------该函数的核心作用是在 Compose 生命周期内执行挂起函数,且仅在依赖参数变化时重新执行。这里我们将 text 作为依赖项,确保文本变化时动画会重新触发。

在 LaunchedEffect 内部,通过循环遍历完整文本的每个字符,逐字追加到 textToDisplay 中,并在每次追加后添加延迟,以此模拟打字机的逐字输出效果:

kotlin 复制代码
LaunchedEffect(key1 = text) {
    for (char in text.toCharArray()) {
        textToDisplay += char.toString()
        delay(delay) // 控制每个字符的显示间隔
    }
}

3. 文本展示:动态更新

将 textToDisplay 绑定到 Text 组件,当该状态变量更新时,Text 会自动重组并显示最新的文本内容,从而实现逐字显示的视觉效果:

kotlin 复制代码
Text(
    modifier = modifier,
    text = textToDisplay,
)

4. 回调触发:后续操作

为了增强扩展性,我们添加动画完成后的回调逻辑。即在携程执行完成之后,回调 onDone。

完整代码实现

将上述步骤整合,最终的完整代码如下:

kotlin 复制代码
@Composable
fun TextTypeWriter(
    modifier: Modifier = Modifier,
    text: String,
    delay: Long = 160L,
    onDone: () -> Unit,
) {
    var textToDisplay by remember { mutableStateOf("") }

    LaunchedEffect(key1 = text) {
        for (char in text.toCharArray()) {
            textToDisplay += char.toString()
            delay(delay)
        }
        onDone.invoke()
    }

    Text(
        modifier = modifier,
        text = textToDisplay,
    )
}

使用示例

只需在你的 Composable 布局中直接调用该函数,即可快速实现打字机动画:

kotlin 复制代码
// 示例:在屏幕中央显示打字机动画文本
Box(
    modifier = Modifier.fillMaxSize(),
    contentAlignment = Alignment.Center,
) {
    TextTypeWriter(text = "I Love Android Development") {
        Log.d("TyW", "Done")
    }
}

我们看下效果:

还不错!

小优化一下

实际上这个效果还有个小优化空间,AI 的 SSE 接口一般返回来的数据,并不是匀速的,所以我们可以让打字机的效果带有随机的延迟,让其打印的延迟在一个区间,这样会更加真实。

优化后代码如下:

Kotlin 复制代码
@Composable
fun TextTypeWriter(
    modifier: Modifier = Modifier,
    text: String,
    delayRange: LongRange = 10L..400L, // 默认的随机延迟
    onDone: () -> Unit,
) {
    var textToDisplay by remember { mutableStateOf("") }

    LaunchedEffect(key1 = text) {
        for (char in text.toCharArray()) {
            textToDisplay += char.toString()
            delay(delayRange.random()) // LongRange.random() 随机选择
        }
        onDone.invoke()
    }

    Text(
        modifier = modifier,
        text = textToDisplay,
    )
}

看看效果:

嗯,就这样!

总结

通过本文,你已掌握了 Jetpack Compose 中打字机动画的核心实现逻辑。该方案代码简洁、复用性强,可通过参数灵活调整动画效果,满足不同场景的需求。

相关推荐
半摆烂日常7 小时前
低代码平台API对接实践:接口鉴权与数据同步的完整实现
android·低代码·rxjava
事圆则缓7 小时前
volatile 使用场景全解析:它能保证什么,又解决不了什么
android
蒲公英内测分发8 小时前
智能投影仪参加海外展会,未上架的 Android 配套 App 怎么让客户限时试用?
android
ii_best8 小时前
按键精灵手机端开发安卓版实战:手写一个可最小化、可拖动的「运行日志悬浮窗」(附完整 源码 + 踩坑记录)
android·ios·智能手机·自动化·ai编程·按键精灵
终端安全笔记8 小时前
安卓做 MDM 管控,先分清三种注册入口
android·安全·智能手机
乌萨达9 小时前
手机模拟器安卓怎么用?电脑安装应用、玩手游与账号同步指南
android·智能手机·电脑·雷电模拟器
美狐美颜SDK开放平台10 小时前
Android与iOS直播APP美颜有什么区别?视频美颜SDK开发详解
android·ios·音视频·视频美颜sdk
春猿火12 小时前
某市-2026【网安·论道】misc-afterimage_note-wp
android
恋猫de小郭13 小时前
Shopify 回应为什么从 RN 回到原生,为什么不用 KMP ?
android·前端·flutter
fundroid14 小时前
Android AI 开发,真正拉开差距的是工程闭环
android·ai·大模型·agent