Jetpack Compose Dialog中AnimatedContent的尺寸变化动画过渡不流畅问题
Jetpack Compose Dialog中AnimatedContent的尺寸变化动画过渡不流畅问题
我来帮你搞定这个Dialog里尺寸动画生硬的问题~ 你的代码目前只给内容加了淡入淡出效果,但完全没处理尺寸变化的过渡逻辑,而且Dialog的外层Surface也没跟着内容的尺寸变化做平滑适配,这就是动画看起来跳变的核心原因。
问题根源拆解
- 你当前的
transitionSpec仅配置了淡入淡出,没有针对内容的高度差异添加尺寸动画; - Dialog的Surface默认不会自动跟随内部内容的尺寸变化做动画,导致Dialog边框直接跳变。
修复方案
我们需要给AnimatedContent添加尺寸变换动画(sizeTransform),并将其与原有的淡入淡出效果结合,同时确保父布局自适应内容高度,让Dialog的整体尺寸跟着内容平滑变化。
下面是修改后的完整代码:
@Composable fun DialogWithAnimation() { var state by remember { mutableIntStateOf(0) } Dialog(onDismissRequest = {}) { Surface( shape = AlertDialogDefaults.shape, // 让Surface自适应内容尺寸,跟随内部动画变化 modifier = Modifier.wrapContentSize() ) { Column( // 让Column自适应内容高度,不强制填充 modifier = Modifier.wrapContentHeight() ) { // Header 部分保持原逻辑不变 Row( modifier = Modifier .height(40.dp) .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(16.dp) ) { MyHeaderButton( modifier = Modifier.weight(1f), isActive = state == 0, label = "A" ) { state = 0 } MyHeaderButton( modifier = Modifier.weight(1f), isActive = state == 1, label = "B" ) { state = 1 } } AnimatedContent( targetState = state, label = "A-B-content", transitionSpec = { // 组合尺寸变换动画 + 淡入淡出动画 (sizeTransform(animationSpec = tween(300)) togetherWith fadeIn(animationSpec = tween(220)) togetherWith fadeOut(animationSpec = tween(90))).using( // 关闭裁剪,避免内容在尺寸变化时被截断 SizeTransform(clip = false) ) } ) { target -> if (target == 0) { Box( modifier = Modifier .fillMaxWidth() .height(100.dp) .background(Color.Blue) ) } else { Box( modifier = Modifier .fillMaxWidth() .height(150.dp) .background(Color.Yellow) ) } } } } } }
关键修改点说明
添加
sizeTransform核心过渡:sizeTransform(animationSpec = tween(300))会自动计算新旧内容的尺寸差异,生成平滑的高度变化动画,配合原有的淡入淡出,实现「尺寸渐变+淡入淡出」的自然组合效果。调整父布局的尺寸行为:
给Surface和Column加上自适应尺寸的Modifier,确保它们不会强制固定高度,而是跟随AnimatedContent的尺寸动态调整,这样Dialog的整体边框也会跟着做平滑动画。优化动画节奏:
将尺寸动画时长设为300ms,与淡入淡出的时长(220/90ms)匹配,让整个过渡更协调;如果喜欢弹性更强的动画,可以把tween(300)换成spring()。
预期效果
修改后,切换A/B标签时,蓝色/黄色Box的高度会从100dp平滑过渡到150dp,同时伴随淡入淡出效果,Dialog的整体高度也会跟着内容的变化做无缝调整,不会再出现跳变的情况。
内容来源于stack exchange




