You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中Lottie动画点击切换正反向及状态同步问题

解决方案

问题1:初始isChecked为true时checked被重置

问题根源是初始progress从0触发LaunchedEffect,将checked强制改为false。解决方式是让progress初始值与isChecked绑定,同时避免浮点数精确比较的误差。

问题2:从动画末尾反向播放

通过给animateLottieCompositionAsState指定initialValue,让初始进度直接跳到1f(当isChecked=true时),再设置负速度实现反向播放。

修改后的完整代码

private fun LottieAnim(
    modifier: Modifier = Modifier,
    isChecked: Boolean = true,
    res: Int
) {
    val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(res))
    val currentIsChecked by rememberUpdatedState(isChecked)
    var checked by remember { mutableStateOf(currentIsChecked) }
    var isPlaying by remember { mutableStateOf(false) }

    val progress by animateLottieCompositionAsState(
        composition = composition,
        restartOnPlay = false,
        isPlaying = isPlaying,
        speed = if (checked) -1f else 1f,
        clipSpec = LottieClipSpec.Progress(0f, 1f),
        // 初始进度与checked绑定:true时从末尾(1f)开始,false时从开头(0f)开始
        initialValue = if (currentIsChecked) 1f else 0f
    )

    // 同步外部传入的isChecked参数变化
    LaunchedEffect(currentIsChecked) {
        checked = currentIsChecked
        isPlaying = false
    }

    LottieAnimation(
        composition,
        progress = { progress },
        modifier = modifier.clickable {
            checked = !checked
            isPlaying = true
        }
    )

    LaunchedEffect(progress) {
        // 用近似值判断,规避浮点数精度问题
        if (progress >= 0.99f) {
            Log.i("INFO", "Animation End")
            isPlaying = false
            checked = true
        }
        if (progress <= 0.01f) {
            Log.i("INFO", "Animation Start")
            isPlaying = false
            checked = false
        }
    }
}

除progress外判断动画起止状态的方式

  • animateLottieCompositionAsState内置onAnimationEnd回调:动画自然结束时自动触发,无需手动监听进度
    val progress by animateLottieCompositionAsState(
        // 其他参数...
        onAnimationEnd = {
            Log.i("INFO", "Animation finished")
            isPlaying = false
            checked = !checked
        }
    )
    
  • Lottie Composition监听器:给加载完成的Composition添加状态监听器,直接捕获动画起止事件
    val composition by rememberLottieComposition(LottieCompositionSpec.RawRes(res)) { _, _ ->
        composition?.let {
            it.addListener(object : LottieListener {
                override fun onAnimationEnd() {
                    // 处理结束逻辑
                }
                override fun onAnimationStart() {
                    // 处理开始逻辑
                }
            })
        }
    }
    
  • 结合isPlaying状态判断:当isPlaying从true切换为false,且进度处于0f或1f附近时,可判定动画停止在起止点

内容的提问来源于stack exchange,提问作者Nicolas DUBOSCQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 21:35:25