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

动画时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
            )
        }
@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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:12:13