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

如何在Jetpack Compose自定义Composable中实现水平缩放显隐动画?

实现仅X轴的搜索栏显示动画

针对你的需求,这里提供两种可行方案,均仅沿X轴实现搜索栏的显示/隐藏动画,避免Y轴的多余动画:

方案一:自定义缩放动画(仅X轴)

使用AnimatedVisibility并自定义进入/退出动画,强制Y轴缩放保持原始大小,只动画X轴的缩放比例:

// 定义仅X轴的进入/退出动画
val searchEnter = scaleIn(
    initialScaleX = 0f,
    initialScaleY = 1f, // Y轴保持原始大小,不参与动画
    animationSpec = tween(durationMillis = 300, easing = LinearOutSlowInEasing)
) + fadeIn()

val searchExit = scaleOut(
    targetScaleX = 0f,
    targetScaleY = 1f, // Y轴保持原始大小,不参与动画
    animationSpec = tween(durationMillis = 300, easing = FastOutLinearInEasing)
) + fadeOut()

// 替换原AnimatedContent为AnimatedVisibility
AnimatedVisibility(
    visible = isSearchBarVisible,
    enter = searchEnter,
    exit = searchExit
) {
    Row(
        modifier = Modifier
            .padding(
                start = screenWidth * 0.08f,
                end = 16.dp,
                top = 8.dp,
                bottom = 8.dp
            ),
        verticalAlignment = Alignment.CenterVertically
    ) {
        SearchBar(
            hint = "Buscar oração",
            onTextChange = { newText -> searchText = newText },
            onSearchClicked = { focusManager.clearFocus() },
            onBackClicked = {
                isSearchBarVisible = false
                searchText = ""
            },
            focusRequester = focusRequester
        )
    }
}

方案二:宽度从0到目标值的动画

通过animateDpAsState控制搜索栏的宽度,从0平滑过渡到目标宽度,实现纯X轴的尺寸展开动画:

// 计算搜索栏的目标宽度(减去左右padding后的可用宽度)
val targetWidth = screenWidth - screenWidth * 0.08f - 16.dp

// 动画宽度状态
val searchWidth by animateDpAsState(
    targetValue = if (isSearchBarVisible) targetWidth else 0.dp,
    animationSpec = tween(durationMillis = 300, easing = LinearOutSlowInEasing)
)

// 使用AnimatedContent确保动画过渡流畅
AnimatedContent(targetState = isSearchBarVisible) { visible ->
    if (visible || searchWidth > 0.dp) { // 确保动画过程中内容可见
        Row(
            modifier = Modifier
                .padding(
                    start = screenWidth * 0.08f,
                    end = 16.dp,
                    top = 8.dp,
                    bottom = 8.dp
                )
                .width(searchWidth) // 绑定动画宽度
                .clip(RoundedCornerShape(16.dp)), // 可选:添加圆角避免宽度变化时的生硬感
            verticalAlignment = Alignment.CenterVertically
        ) {
            SearchBar(
                hint = "Buscar oração",
                onTextChange = { newText -> searchText = newText },
                onSearchClicked = { focusManager.clearFocus() },
                onBackClicked = {
                    isSearchBarVisible = false
                    searchText = ""
                },
                focusRequester = focusRequester
            )
        }
    }
}

方案选择建议

  • 若需要缩放展开/收起的效果,选择方案一;
  • 若需要从左到右逐步拉长的尺寸动画,选择方案二。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 10:37:28