Jetpack Compose:updateTransition完成监听与动画顺序实现问询
Jetpack Compose 动画问题解决方案
先看你提供的基础代码:
val transition = updateTransition(animValue, label = "iconstate") val offsetVal by transition.animateFloat( label = "rocket1 offset" ) { animated -> Log.d("Wuh", "AnimatedIconMovement hjhjdahda: $animated") if (animated) 1f else 0f } val sizeAnimate by transition.animateDp(label="size dp", targetValueByState = { if(it) 60.dp else 20.dp })
问题1:监听updateTransition的动画完成状态
有两种实用方式:
方式1:添加状态变化监听器
直接给transition绑定addStatusChangeListener,当动画状态变为Completed时触发回调:
transition.addStatusChangeListener { status -> if (status == TransitionStatus.Completed) { // 这里写动画完成后的逻辑,比如打印日志、触发后续操作 Log.d("Animation", "整个Transition动画执行完毕") } }
方式2:用LaunchedEffect监听状态同步
通过对比transition的currentState和targetState,当两者相等时说明动画完成:
LaunchedEffect(transition.targetState) { snapshotFlow { transition.currentState == transition.targetState } .filter { it } .collect { Log.d("Animation", "Transition动画已完成") // 执行动画完成后的操作 } }
问题2:实现offsetVal动画先执行,完成后再启动sizeAnimate动画
核心是分阶段控制动画触发时机,以下两种方案都可行:
方案1:用多状态枚举拆分动画阶段
定义密封类标记动画的不同阶段,让updateTransition基于状态逐步切换:
// 定义动画阶段状态 sealed class AnimationPhase { object Idle : AnimationPhase() object RunningOffset : AnimationPhase() object RunningSize : AnimationPhase() } // 持有当前动画阶段的状态 var currentPhase by remember { mutableStateOf(AnimationPhase.Idle) } // 触发顺序动画的入口(比如绑定到点击事件) fun startSequentialAnimation() { currentPhase = AnimationPhase.RunningOffset } // 负责offset动画的Transition val offsetTransition = updateTransition(currentPhase, label = "offset-transition") val offsetVal by offsetTransition.animateFloat(label = "rocket1 offset") { phase -> when (phase) { AnimationPhase.RunningOffset -> 1f else -> 0f } } // 监听offset动画完成,切换到size动画阶段 LaunchedEffect(offsetTransition.targetState) { snapshotFlow { offsetTransition.currentState == offsetTransition.targetState } .filter { it && offsetTransition.targetState == AnimationPhase.RunningOffset } .collect { currentPhase = AnimationPhase.RunningSize } } // 负责size动画的Transition val sizeTransition = updateTransition(currentPhase, label = "size-transition") val sizeAnimate by sizeTransition.animateDp(label = "size dp") { phase -> when (phase) { AnimationPhase.RunningSize -> 60.dp else -> 20.dp } }
方案2:利用单个动画的finishedListener触发后续动画
拆分两个独立状态变量,在offset动画完成后触发size动画的状态切换:
// 分别控制offset和size动画的状态变量 var animateOffset by remember { mutableStateOf(false) } var animateSize by remember { mutableStateOf(false) } // 触发顺序动画的入口 fun startSequentialAnimation() { animateOffset = true } // offset动画,完成后启动size动画 val offsetVal by updateTransition(animateOffset, label = "offset-transition").animateFloat( label = "rocket1 offset", finishedListener = { // offset动画执行完毕,触发size动画 animateSize = true } ) { animated -> if (animated) 1f else 0f } // size动画 val sizeAnimate by updateTransition(animateSize, label = "size-transition").animateDp( label = "size dp" ) { animated -> if (animated) 60.dp else 20.dp }
内容的提问来源于stack exchange,提问作者Gaurav Roy
相关产品推荐
相关产品推荐

