Jetpack Compose:无需硬编码值实现wrapContentSize与fillMaxSize动画切换
实现Compose组件在wrapContentSize与fillMaxSize间的双向动画切换
问题分析
你当前的代码存在两个核心问题:
- 将
Modifier存储为mutableState是冗余且错误的——Compose中Modifier应根据状态动态生成,而非保存为状态变量。 animateContentSize主要用于内容自身变化时的尺寸动画,而你需要的是容器主动在wrapContentSize和fillMaxSize之间切换,该API无法直接满足这种场景。
解决方案
使用BoxWithConstraints获取父容器的可用尺寸,结合animateSizeAsState实现两种状态间的平滑过渡,无需硬编码任何数值:
@Composable fun ExpandableBox() { var expanded by remember { mutableStateOf(false) } // 记录初始wrap状态下的组件尺寸 var wrapSize by remember { mutableStateOf(Size.Zero) } BoxWithConstraints(modifier = Modifier.fillMaxSize()) { // 根据展开状态确定目标尺寸 val targetSize = if (expanded) { Size(maxWidth.toPx(), maxHeight.toPx()) } else { wrapSize } // 尺寸动画 val animatedSize by animateSizeAsState( targetValue = targetSize, animationSpec = tween(3000, easing = LinearEasing), label = "expandAnimation" ) Box( modifier = Modifier // 应用动画后的尺寸 .size(animatedSize.width.dp, animatedSize.height.dp) .background(Color.Green) .clickable { expanded = !expanded } // 首次渲染时记录wrap状态的尺寸 .onSizeChanged { size -> if (!expanded && wrapSize == Size.Zero) { wrapSize = Size(size.width.toFloat(), size.height.toFloat()) } }, contentAlignment = Alignment.Center ) { Text(text = "Testing....") } } }
代码说明
BoxWithConstraints:提供父容器的maxWidth和maxHeight,作为fillMaxSize状态的目标尺寸。wrapSize:通过onSizeChanged在组件首次以wrapContentSize渲染时记录其真实尺寸,作为收起状态的目标尺寸。animateSizeAsState:负责在wrapSize和父容器尺寸之间执行平滑的尺寸过渡动画。- 点击事件直接切换
expanded状态,触发动画更新。
内容的提问来源于stack exchange,提问作者It's me guys
相关产品推荐
相关产品推荐

