如何在amount变量变化时重启Lottie动画?解决多次触发失效问题
问题原因分析
currentAmount仅通过remember存储初始值,未监听amount的变化做同步更新,后续amount变更时currentAmount不会随之改变,导致playAnimation的判断逻辑失效。restartOnPlay设为false,意味着isPlaying从false变回true时,动画会从上次暂停的位置继续,而非从头启动,所以后续触发时看不到预期的“重启”效果。- 直接在Composable函数体中赋值
oldAmount = currentAmount不符合Composable的状态更新规范,容易引发状态不一致问题。
修复后的代码
@Composable private fun Lottie( amount: Long ) { // 跟踪最新的amount参数值 val latestAmount by rememberUpdatedState(amount) var lastTriggeredAmount by remember { mutableStateOf(0L) } var playAnimation by remember { mutableStateOf(false) } // 监听amount变化,触发并管理动画播放 LaunchedEffect(latestAmount) { // 跳过初始值0的触发(业务不需要可移除) if (lastTriggeredAmount != 0L && latestAmount != lastTriggeredAmount) { playAnimation = true // 等待动画播放完成后重置状态,确保下次变更能再次触发 composition?.duration?.let { delay(it) } ?: delay(1000L) playAnimation = false } lastTriggeredAmount = latestAmount } val composition by rememberLottieComposition( LottieCompositionSpec.RawRes(R.raw.my_animation) ) val progress by animateLottieCompositionAsState( composition, isPlaying = playAnimation, speed = 1f, restartOnPlay = true, // 开启播放时重启动画 cancellationBehavior = LottieCancellationBehavior.OnIterationFinish ) LottieAnimation(composition = composition, progress = progress) }
关键修改点
- 用
rememberUpdatedState跟踪最新的amount参数,确保Composable重组时能获取到最新值。 - 通过
LaunchedEffect监听amount变化,触发动画并在播放完成后重置状态,保证每次amount变更都能触发新的动画循环。 - 将
restartOnPlay设为true,确保每次触发动画都从头开始播放。 - 移除了原代码中不合理的状态直接赋值逻辑,改用
LaunchedEffect处理异步状态更新,符合Jetpack Compose的状态管理规范。
内容的提问来源于stack exchange,提问作者Evgeny Fedin
相关产品推荐
相关产品推荐

