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

Jetpack Compose:animateDp隐藏时下滑动画不生效问题

问题分析

当前弹窗隐藏时仅淡出无下滑动画的核心原因:你用AnimatedVisibility包裹了Dialog组件,当visibility变为false时,AnimatedVisibility的fadeOut退出动画会优先将Dialog从布局中移除,导致translateY的位移动画还未执行完成就被销毁,自然看不到下滑效果。

解决方案

移除AnimatedVisibility,改用updateTransition同时控制背景透明度与Card位移动画,确保动画完整执行后再关闭弹窗。修改后的代码如下:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun DialogBottomSheets(
    isVisible: Boolean,
    onDismiss: () -> Unit,
    content: @Composable () -> Unit,
    modifier: Modifier = Modifier
) {
    val mutableInteractionSource = MutableInteractionSource()
    val screenHeight = rememberWindowInfo().screenHeight

    // 用updateTransition统一管理显示/隐藏状态与动画
    val transition = updateTransition(targetState = isVisible, label = "BottomSheetTransition")
    
    // 背景透明度动画:显示时半透明,隐藏时完全透明
    val backgroundAlpha by transition.animateFloat(
        transitionSpec = { tween(200) },
        label = "BackgroundAlpha"
    ) { visible -> if (visible) 0.5f else 0f }
    
    // Card位移动画:显示时在底部,隐藏时滑出屏幕
    val translateY by transition.animateDp(
        transitionSpec = { tween(200) },
        label = "CardTranslateY"
    ) { visible -> if (visible) 0.dp else screenHeight }

    // 监听动画结束:从显示转隐藏时,等动画跑完再执行关闭回调
    LaunchedEffect(transition.currentState, transition.targetState) {
        if (transition.currentState && !transition.targetState) {
            transition.awaitTransitionComplete()
            onDismiss()
        }
    }

    // 弹窗显示逻辑:目标状态为显示,或正在执行隐藏动画时,保持Dialog存在
    if (isVisible || transition.currentState) {
        Dialog(
            onDismissRequest = { onDismiss() },
            properties = DialogProperties(
                usePlatformDefaultWidth = false,
                dismissOnBackPress = true,
                dismissOnClickOutside = true
            ),
        ) {
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(color = Color.Black.copy(alpha = backgroundAlpha))
                    .clickable(
                        interactionSource = mutableInteractionSource,
                        indication = null
                    ) { onDismiss() },
                contentAlignment = Alignment.BottomCenter
            ) {
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .wrapContentHeight()
                        .offset(y = translateY)
                        .clickable(
                            interactionSource = mutableInteractionSource,
                            indication = null
                        ) {}, // 阻止点击Card内部触发关闭
                    backgroundColor = Color.White,
                    shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp)
                ) {
                    content()
                }
            }
        }
    }
}
关键修改说明
  1. 移除AnimatedVisibility:避免弹窗在动画中途被移除,保证位移动画完整执行。
  2. 双动画同步控制:用updateTransition同时驱动背景透明度和Card位移,实现显示时上滑+背景淡入、隐藏时下滑+背景淡出的同步效果。
  3. 动画结束监听:通过LaunchedEffect等待隐藏动画完成后再调用onDismiss,确保视觉效果完整。
  4. 点击事件处理:给Card添加空的clickable阻止事件透传,实现点击弹窗外部才关闭的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 09:44:53