能否跟踪AnimatedVisibility动画结束?实现元素显隐切换遇问题求助
问题:Compose中点击按钮实现元素先消失再重新显示的动画异常
想要实现点击按钮后,元素先执行退出动画消失,再执行进入动画重新显示的效果,但目前元素重新显示时会出现在退出动画移动到的同一侧,达不到预期。
原代码如下:
@Composable fun Greeting() { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { val visibleState = remember { MutableTransitionState(initialState = true).apply { targetState = true } } AnimatedVisibility( visibleState = visibleState, enter = slideInHorizontally( animationSpec = tween(100, easing = LinearEasing), initialOffsetX = { it } ), exit = slideOutHorizontally ( animationSpec = tween(100, easing = LinearEasing), targetOffsetX = { -it } ) ) { RedBox() } Button { visibleState.targetState = false } DisposableEffect(visibleState.currentState) { onDispose { visibleState.targetState = true } } } }
解决方案
问题原因
原代码中使用DisposableEffect监听currentState,当currentState变为false时会立即触发onDispose并设置targetState=true,导致退出动画还未完成就开始执行进入动画,状态切换冲突。同时,未确保两次动画之间有明确的间隔和状态重置。
修改后的代码
@Composable fun Greeting() { Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { val visibleState = remember { MutableTransitionState(true) } val animationDuration = 100 // 和动画时长保持一致 AnimatedVisibility( visibleState = visibleState, enter = slideInHorizontally( animationSpec = tween(animationDuration, easing = LinearEasing), initialOffsetX = { it } // 从右侧滑入 ), exit = slideOutHorizontally( animationSpec = tween(animationDuration, easing = LinearEasing), targetOffsetX = { -it } // 向左侧滑出 ) ) { RedBox() } Button(onClick = { // 仅当当前状态为显示时,触发隐藏 if (visibleState.currentState) { visibleState.targetState = false } }) { Text("触发动画") } // 监听targetState变化,等待退出动画完成后重新显示 LaunchedEffect(visibleState.targetState) { if (!visibleState.targetState) { delay(animationDuration.toLong()) visibleState.targetState = true } } } } @Composable fun RedBox() { Box( modifier = Modifier .size(50.dp) .background(Color.Red) ) }
关键修改点
- 用
LaunchedEffect替代DisposableEffect:监听targetState的变化,当元素开始执行退出动画(targetState=false)时,等待与动画时长一致的时间后,再将targetState设为true,确保退出动画完全结束后才启动进入动画。 - 增加状态判断:点击按钮时仅在元素处于显示状态时触发隐藏,避免重复触发导致的状态混乱。
- 统一动画时长:将动画时长提取为变量,确保延迟时间和动画时长匹配,保证动画衔接自然。
这样修改后,点击按钮元素会先向左滑出消失,等待动画结束后再从右侧滑入重新显示,符合预期效果。
内容的提问来源于stack exchange,提问作者CyllXap4ok
相关产品推荐
相关产品推荐

