You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose中如何实现Column尺寸缩至0.dp的动画效果

问题描述

希望在所有动画完成后将Column的尺寸设置为0.dp,即子元素全部隐藏后让Column收缩至0.dp。尝试的代码运行后,动画完成仍有残留空间,使用animateSizeAsState时出现类型不匹配错误:

Type mismatch.
 Required:  Size
 Found: { Comparable  & Number }
解决方案

1. 修复animateSizeAsState类型不匹配问题

animateSizeAsState的targetValue参数要求是Size类型,而非单纯数值。需要将目标尺寸封装为Size对象:

  • 显示状态:用onGloballyPositioned获取的Column实际尺寸创建Size
  • 隐藏状态:直接使用Size(0f, 0f)

2. 同步子元素动画与Column尺寸动画

将所有动画的时长保持一致,确保子元素消失动画和Column收缩动画同步。也可以让子元素随Column收缩自然隐藏,简化实现逻辑。

修改后的完整代码

@Preview(showBackground = true)
@Composable
fun MoveText() {
    var columnSize by remember { mutableStateOf(Size.Zero) }
    var visible by remember { mutableStateOf(true) }
    
    // Column尺寸收缩动画
    val animatedSize by animateSizeAsState(
        targetValue = if (visible) columnSize else Size.Zero,
        animationSpec = tween(durationMillis = 1000)
    )

    ScrollComposeTheme {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 16.dp, top = 16.dp)
        ) {
            Column(
                modifier = Modifier
                    .onGloballyPositioned { coordinates ->
                        // 记录Column初始像素尺寸
                        columnSize = Size(
                            width = coordinates.size.width.toFloat(),
                            height = coordinates.size.height.toFloat()
                        )
                    }
                    .size(animatedSize.width.dp, animatedSize.height.dp)
                    .background(Color.LightGray)
            ) {
                Image(
                    modifier = Modifier.padding(top = 13.dp),
                    alpha = if (visible) 1f else 0f,
                    imageVector = Icons.Default.ShoppingCart,
                    contentDescription = null,
                )
                Text(
                    modifier = Modifier.padding(top = 6.dp),
                    text = "Hello, Anna",
                    fontSize = 20.sp,
                    color = Color.Black.copy(alpha = if (visible) 1f else 0f),
                )
            }
            Button(
                modifier = Modifier.padding(top = 10.dp),
                onClick = { visible = !visible }
            ) {
                Text(text = "Move Text")
            }
        }
    }
}

额外优化建议

  • 如果需要子元素偏移动画和Column收缩更贴合,可以根据动画尺寸的比例计算偏移量:
    val offsetRatio = if (columnSize.height == 0f) 1f else animatedSize.height / columnSize.height
    val iconOffset = 13.dp * offsetRatio
    
  • 更简洁的实现方式:使用animateContentSize,自动根据内容显示/隐藏触发尺寸收缩动画:
    Column(
        modifier = Modifier
            .animateContentSize(tween(1000))
            .background(Color.LightGray)
    ) {
        if (visible) {
            Image(modifier = Modifier.padding(top = 13.dp),
                  imageVector = Icons.Default.ShoppingCart,
                  contentDescription = null)
            Text(modifier = Modifier.padding(top = 6.dp),
                 text = "Hello, Anna",
                 fontSize = 20.sp)
        }
    }
    

内容的提问来源于stack exchange,提问作者Compose Learner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:25:04