You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Jetpack Compose Dialog中AnimatedContent的尺寸变化动画过渡不流畅问题

Jetpack Compose Dialog中AnimatedContent的尺寸变化动画过渡不流畅问题

我来帮你搞定这个Dialog里尺寸动画生硬的问题~ 你的代码目前只给内容加了淡入淡出效果,但完全没处理尺寸变化的过渡逻辑,而且Dialog的外层Surface也没跟着内容的尺寸变化做平滑适配,这就是动画看起来跳变的核心原因。

问题根源拆解

  1. 你当前的transitionSpec仅配置了淡入淡出,没有针对内容的高度差异添加尺寸动画;
  2. 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)
                        )
                    }
                }
            }
        }
    }
}

关键修改点说明

  1. 添加sizeTransform核心过渡
    sizeTransform(animationSpec = tween(300))会自动计算新旧内容的尺寸差异,生成平滑的高度变化动画,配合原有的淡入淡出,实现「尺寸渐变+淡入淡出」的自然组合效果。

  2. 调整父布局的尺寸行为
    SurfaceColumn加上自适应尺寸的Modifier,确保它们不会强制固定高度,而是跟随AnimatedContent的尺寸动态调整,这样Dialog的整体边框也会跟着做平滑动画。

  3. 优化动画节奏
    将尺寸动画时长设为300ms,与淡入淡出的时长(220/90ms)匹配,让整个过渡更协调;如果喜欢弹性更强的动画,可以把tween(300)换成spring()

预期效果

修改后,切换A/B标签时,蓝色/黄色Box的高度会从100dp平滑过渡到150dp,同时伴随淡入淡出效果,Dialog的整体高度也会跟着内容的变化做无缝调整,不会再出现跳变的情况。

内容来源于stack exchange

火山引擎 最新活动