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

Android中如何实现Lottie动画的无缝切换?

解决Lottie动画切换时的闪烁问题

问题分析

你当前的实现直接通过切换animationRes更换动画,每次切换都会重新加载对应的LottieComposition。由于加载需要时间,这段间隙会导致画面空白,从而出现闪烁现象。要实现无缝过渡,核心是预加载所有需要的动画资源,并通过过渡动画衔接不同状态。

解决方案

下面是优化后的代码,主要做了这几点改进:

  1. 预加载所有三个Lottie动画的Composition,避免切换时的加载延迟
  2. 使用LottieAnimationSwitcher实现平滑过渡,消除闪烁
  3. 利用动画结束回调自动切回 idle 状态,比固定delay更适配不同动画时长
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.gestures.detectDragGestures
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.tooling.preview.Preview
import com.airbnb.lottie.compose.*
import com.lumen.tomo.R

// 定义动画类型枚举,方便管理状态
private enum class AnimationType {
    IDLE, TAP, SWIPE
}

@Composable
fun ChatView() {
    // 预加载所有需要的Lottie动画资源
    val idleComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.cat_idle))
    val tapComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.cat_headshake))
    val swipeComposition by rememberLottieComposition(LottieCompositionSpec.RawRes(R.raw.cat_heart))

    var currentAnimation by remember { mutableStateOf(AnimationType.IDLE) }

    LottieAnimationSwitcher(
        targetState = currentAnimation,
        // 设置淡入淡出过渡,消除切换时的闪烁
        transitionSpec = { fadeIn() with fadeOut() },
        modifier = Modifier
            .fillMaxSize()
            .pointerInput(Unit) {
                detectTapGestures(onTap = {
                    currentAnimation = AnimationType.TAP
                })
                detectDragGestures { _, _ ->
                    currentAnimation = AnimationType.SWIPE
                }
            }
    ) { currentState ->
        val (composition, iterations) = when (currentState) {
            AnimationType.IDLE -> idleComposition to LottieConstants.IterateForever
            AnimationType.TAP -> tapComposition to 1
            AnimationType.SWIPE -> swipeComposition to 1
        }

        LottieAnimation(
            composition = composition,
            iterations = iterations,
            onAnimationEnd = {
                // 非idle动画播放结束后,自动切回idle状态
                if (currentState != AnimationType.IDLE) {
                    currentAnimation = AnimationType.IDLE
                }
            }
        )
    }
}

@Preview
@Composable
fun ChatViewPreview() {
    ChatView()
}

额外说明

  • 预加载的Composition会被remember缓存,不会重复加载,确保切换时资源已就绪
  • LottieAnimationSwitcher会自动处理新旧动画的过渡,这里用淡入淡出可以让切换更自然,你也可以根据需求替换成其他过渡效果(比如滑入滑出)
  • 使用onAnimationEnd回调替代固定delay,能准确匹配动画实际时长,避免提前或延迟切回idle状态

内容的提问来源于stack exchange,提问作者Dayem Saeed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:32:42