Compose中Column内带weight的Box与AnimatedVisibility动画不同步问题
解决Jetpack Compose中顶部Weight布局不跟随底部AnimatedVisibility动画过渡的问题
核心问题在于:AnimatedVisibility仅处理自身的显示/隐藏动画,但Column的weight布局会基于当前可用空间瞬间计算尺寸,导致顶部区域直接跳转到最终位置。要让顶部区域平滑过渡,需要让父布局的尺寸变化也加入动画,并且和AnimatedVisibility的动画参数保持一致。
具体解决方案
给包裹布局的Column添加animateContentSize修饰符,同步动画的时长和曲线,让整个布局的尺寸变化平滑过渡,从而带动顶部weight布局的高度变化:
@Composable fun AnimatedLayoutDemo() { var isBottomVisible by remember { mutableStateOf(false) } // 统一动画参数,确保和AnimatedVisibility保持一致 val animationSpec = tween( durationMillis = 300, easing = FastOutSlowInEasing ) Column( modifier = Modifier .fillMaxSize() // 让Column的内容尺寸变化带有动画 .animateContentSize(animationSpec = animationSpec) ) { // 顶部可点击的黄色区域 Box( modifier = Modifier .weight(1f) .fillMaxWidth() .background(Color.Yellow) .clickable { isBottomVisible = !isBottomVisible } ) { Text(text = "点击切换底部区域显示/隐藏", modifier = Modifier.align(Alignment.Center)) } // 底部洋红色区域,使用AnimatedVisibility实现滑入滑出 AnimatedVisibility( visible = isBottomVisible, enter = slideInVertically( initialOffsetY = { it }, // 从自身高度的位置滑入 animationSpec = animationSpec ), exit = slideOutVertically( targetOffsetY = { it }, // 滑出到自身高度的位置 animationSpec = animationSpec ) ) { Box( modifier = Modifier .fillMaxWidth() .height(200.dp) .background(Color.Magenta) ) } } }
原理说明
animateContentSize会监听Column的内容尺寸变化,并为这个变化添加动画过渡,这样当底部区域显示/隐藏时,Column的可用空间变化会是平滑的。- 顶部的
weight=1f布局会基于Column的实时可用空间动态调整高度,随着Column的尺寸动画,顶部区域的高度也会平滑过渡,不再瞬间跳转。 - 统一
animateContentSize和AnimatedVisibility的animationSpec,确保两个动画的速度、曲线完全匹配,视觉上更协调自然。
内容的提问来源于stack exchange,提问作者Lloyd Hussell
相关产品推荐
相关产品推荐

