Jetpack Compose实现盒子依次延迟1秒动画时delay.value不更新问题
问题根源
- 所有Box共用了同一个动画实例和Modifier,天然不可能出现先后动画的效果
- 动画初始化时已经读取了初始的
delay.value=0,后续循环中修改delay.value的时候,已经创建好的动画不会响应这个更新,而且你在组合阶段直接修改MutableState的值还会触发不必要的重组,甚至可能导致无限循环 - 你定义的delay状态完全没必要,每个盒子的延迟可以直接通过遍历的index计算得到
修正后代码
@Composable fun Rocket( isRocketEnabled: Boolean, maxWidth: Dp, maxHeight: Dp ) { val tileSize = 50.dp // 颜色列表用remember包裹避免重复创建 val colorList = remember { listOf( Color(0xffDFFF00), Color(0xffFFBF00), Color(0xffFF7F50), Color(0xffDE3163), Color(0xff9FE2BF), Color(0xff40E0D0), Color(0xff6495ED), Color(0xffCCCCFF), ) } // 每个颜色对应独立的Box和动画逻辑 colorList.forEachIndexed { index, color -> val modifier = if (!isRocketEnabled) { Modifier.offset(y = maxHeight - tileSize) } else { // 每个Box单独创建动画实例 val infiniteTransition = rememberInfiniteTransition(label = "rocket_$index") val positionState = infiniteTransition.animateFloat( initialValue = 0f, targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween( durationMillis = 2000, // 直接用index计算延迟,不需要额外状态存储 delayMillis = index * 1000, easing = LinearEasing ) ), label = "position_$index" ) Modifier.offset( x = (maxWidth - tileSize) * positionState.value, y = (maxHeight - tileSize) - (maxHeight - tileSize) * positionState.value, ) } Box( modifier = modifier .width(tileSize) .height(tileSize) .background(color = color) ) } }
修正说明
- 把颜色列表的遍历放到最外层,每个颜色对应一个独立的Box,每个Box单独创建自己的动画实例
- 去掉冗余的delay状态,直接用遍历的index计算每个动画的延迟时间,第n个盒子延迟n*1000毫秒启动
- 每个盒子使用独立的Modifier和动画状态,互不干扰,即可实现依次间隔1秒启动的效果
- 对颜色列表做了remember缓存,避免每次重组都创建新的列表,优化性能
内容的提问来源于stack exchange,提问作者Code Poet
相关产品推荐
相关产品推荐

