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

如何使用animateContentSize实现Box在fillMaxSize与0间的尺寸动画?

问题解决:Compose中Box从fillMaxSize缩回到0的动画失效

问题原因

你当前使用的 animateContentSize() 是专门用于组件自身内容尺寸变化的动画API,但你是通过 fillMaxSize(ratio) 基于父容器比例修改Box尺寸,这种依赖父容器的尺寸变更无法被 animateContentSize() 正确捕捉,导致缩小动画失效。同时当 fillMaxSize(0f) 时,Box尺寸变为0,动画系统无法追踪从有尺寸到0的过渡过程。

解决方案一:使用animateFloatAsState驱动比例动画

通过 animateFloatAsState 控制 fillMaxSize() 的比例参数,直接驱动尺寸变化的动画,双向过渡都会生效:

修改TopBar中蓝色Box的代码:

@Composable
fun TopBar(){
    var tabSelected by remember { mutableStateOf(false) }
    // 用animateFloatAsState创建比例动画
    val sizeRatio by animateFloatAsState(
        targetValue = if(tabSelected) 1f else 0f,
        animationSpec = tween(durationMillis = 300) // 可自定义动画时长
    )

    Row(
        modifier = Modifier
            .fillMaxWidth()
            .height(IntrinsicSize.Min)
            .border(1.dp, Color.Black)
            .padding(start = 8.dp, end = 8.dp, top = 7.dp, bottom = 7.dp)
    ){
        // 其他组件保持不变...
        
        Box(
            modifier = Modifier
                .weight(0.25f)
                .fillMaxHeight(),
            contentAlignment = Alignment.Center
        ){
            Box(
                modifier = Modifier
                    .clip(shape = RoundedCornerShape(8.dp))
                    .fillMaxSize(sizeRatio) // 使用动画化的比例值
                    .background(Color.Blue)
                    .clickable(
                        interactionSource = remember { MutableInteractionSource() },
                        indication = null
                    ) {
                        tabSelected = !tabSelected
                    }
            )
            Text(text = "1")
        }
        
        // 其他组件保持不变...
    }
}

解决方案二:用内容驱动animateContentSize动画

让Box的尺寸由内部内容撑开,这样 animateContentSize() 就能正确捕捉尺寸变化,实现双向动画:

修改蓝色Box部分代码:

Box(
    modifier = Modifier
        .weight(0.25f)
        .fillMaxHeight(),
    contentAlignment = Alignment.Center
){
    Box(
        modifier = Modifier
            .clip(shape = RoundedCornerShape(8.dp))
            .animateContentSize()
            .background(Color.Blue)
            .clickable(
                interactionSource = remember { MutableInteractionSource() },
                indication = null
            ) {
                tabSelected = !tabSelected
            }
    ) {
        // 选中时用Spacer撑满整个父容器空间
        if(tabSelected) {
            Spacer(modifier = Modifier.fillMaxSize())
        }
    }
    Text(text = "1")
}

说明

两种方案都能解决你的问题:

  • 方案一更适合需要精确控制尺寸比例的场景,动画过渡更直接。
  • 方案二更贴合animateContentSize()的设计初衷,通过内容变化触发动画。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 00:00:57