如何避免AnimatedVisibility状态变化时内容出现「跳跃」现象?
解决AnimatedVisibility切换时Text组件跳跃的问题
核心原因
AnimatedVisibility仅处理自身按钮的滑入滑出动画,但Row容器的布局尺寸变化是瞬间完成的,导致右侧Text组件直接跳转,无法跟随按钮的动画节奏平滑移动。要解决这个问题,需要让Row的布局尺寸变化也参与动画,保证按钮和Text的动效同步。
具体实现方案
方案1:给Row添加animateContentSize修饰符
这是最简洁的实现方式,通过让Row的尺寸变化伴随过渡动画,带动Text组件平滑移动:
Row( verticalAlignment = CenterVertically, modifier = Modifier .align(CenterVertically) .animateContentSize( // 新增:让Row尺寸变化平滑过渡 animationSpec = tween(durationMillis = 300) // 可自定义动画时长、曲线 ) ) { AnimatedVisibility( visible = buttonBackEnabled, enter = slideInHorizontally(initialOffsetX = { -it }), exit = slideOutHorizontally(targetOffsetX = { -it }) ) { ButtonBack( paddingValues = PaddingValues(0.dp, 0.dp, 5.dp, 0.dp), iconSize = 33.dp ) { mContext.findActivity()?.onBackPressed() } } Text( text = screenTitle, fontSize = 19.sp, fontWeight = FontWeight.SemiBold, modifier = Modifier .align(CenterVertically) ) }
方案2:用AnimatedContent单独控制Text动画
如果需要更精准地控制Text的移动曲线,可以将Text包裹在AnimatedContent中,根据按钮的显隐状态定义独立动画:
Row( verticalAlignment = CenterVertically, modifier = Modifier .align(CenterVertically) ) { AnimatedVisibility( visible = buttonBackEnabled, enter = slideInHorizontally(initialOffsetX = { -it }), exit = slideOutHorizontally(targetOffsetX = { -it }) ) { ButtonBack( paddingValues = PaddingValues(0.dp, 0.dp, 5.dp, 0.dp), iconSize = 33.dp ) { mContext.findActivity()?.onBackPressed() } } AnimatedContent( targetState = buttonBackEnabled, transitionSpec = { // 按钮显示时Text向右移,隐藏时向左移,和按钮动画同步 slideInHorizontally(initialOffsetX = { if (targetState) it else 0 }) with slideOutHorizontally(targetOffsetX = { if (targetState) 0 else -it }) using SizeTransform(clip = false) } ) { _ -> Text( text = screenTitle, fontSize = 19.sp, fontWeight = FontWeight.SemiBold, modifier = Modifier .align(CenterVertically) ) } }
优化提示
- 建议统一按钮和布局动画的时长(比如都设为300ms),避免动效不同步
- 可以给
ButtonBack添加固定宽度修饰符(如.width(40.dp)),让动画的起始/结束位置更稳定 animateContentSize默认使用FastOutSlowInEasing曲线,若需要弹性效果可替换为spring()动画
内容的提问来源于stack exchange,提问作者TriangleN
相关产品推荐
相关产品推荐

