动画时Surface组件阴影与圆角消失问题求助
问题描述
使用Surface组件结合AnimateVisibility实现自定义下拉菜单的垂直展开/收起动画时,动画过程中阴影与圆角消失,变成直角阴影,如何让下拉菜单在动画时保持静态样式?
调用代码
AnimatedVisibility( visible = expanded, enter = expandVertically(animationSpec = tween(2000)), exit = shrinkVertically(animationSpec = tween(2000)) ) { DropDown( modifier = Modifier .width(searchBarSize.dp), list = suggestions, suggestion = suggestionItem ) }
DropDown组件代码
@Composable fun <T> DropDown( modifier: Modifier, list: List<T>, suggestion: @Composable (T, Boolean) -> Unit ) { Surface( shape = RoundedCornerShape(20.dp), elevation = 10.dp, modifier = modifier ) { Column( modifier = Modifier .fillMaxWidth() ) { list.forEachIndexed { index, it -> suggestion(it, index == list.size - 1) } } } }
异常效果展示

解决方案
这个问题源于expandVertically/shrinkVertically动画会在执行过程中临时修改组件的裁剪区域,导致Surface的圆角和阴影无法正常渲染。可以通过以下两种方案解决:
方案一:显式添加裁剪与阴影修饰符
修改DropDown组件,给Surface添加显式的clip修饰符,确保动画过程中圆角被正确裁剪;同时在调用DropDown时额外添加shadow修饰符,避免动画导致阴影丢失:
@Composable fun <T> DropDown( modifier: Modifier, list: List<T>, suggestion: @Composable (T, Boolean) -> Unit ) { Surface( shape = RoundedCornerShape(20.dp), elevation = 10.dp, modifier = modifier .clip(RoundedCornerShape(20.dp)) ) { Column( modifier = Modifier .fillMaxWidth() ) { list.forEachIndexed { index, it -> suggestion(it, index == list.size - 1) } } } }
调用时的代码调整:
AnimatedVisibility( visible = expanded, enter = expandVertically(animationSpec = tween(2000)), exit = shrinkVertically(animationSpec = tween(2000)) ) { DropDown( modifier = Modifier .width(searchBarSize.dp) .shadow(10.dp, RoundedCornerShape(20.dp)), list = suggestions, suggestion = suggestionItem ) }
方案二:改用animateContentSize实现动画(推荐)
放弃expandVertically/shrinkVertically,使用animateContentSize来实现高度变化动画,这种方式能全程保留Surface的圆角与阴影样式,更符合Compose的动画最佳实践:
修改DropDown组件,新增展开状态参数并添加animateContentSize:
@Composable fun <T> DropDown( modifier: Modifier, list: List<T>, suggestion: @Composable (T, Boolean) -> Unit, expanded: Boolean ) { Surface( shape = RoundedCornerShape(20.dp), elevation = 10.dp, modifier = modifier .animateContentSize(animationSpec = tween(2000)) ) { if (expanded) { Column( modifier = Modifier .fillMaxWidth() ) { list.forEachIndexed { index, it -> suggestion(it, index == list.size - 1) } } } } }
调用时直接控制展开状态即可:
DropDown( modifier = Modifier.width(searchBarSize.dp), list = suggestions, suggestion = suggestionItem, expanded = expanded )
内容的提问来源于stack exchange,提问作者D-I-S-C
相关产品推荐
相关产品推荐

