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

Jetpack Compose如何动态修改同一目标页面的导航动画?

在Jetpack Compose中为同一页面设置不同导航动画

要实现同一目标页面在不同场景下使用不同导航动画,核心思路是通过路由参数传递动画类型标识,并在页面的过渡配置中根据该标识动态选择对应的动画效果。以下是具体实现步骤:

1. 定义动画类型枚举(可选但推荐)

创建枚举类统一管理动画类型,避免字符串硬编码:

enum class ScreenAnimation {
    HORIZONTAL, // 右侧滑入
    VERTICAL    // 底部滑入
}

2. 修改路由配置,添加动画参数

在composable配置中为路由添加可选动画参数,并设置默认值:

composable(
    route = "Details?animation={animation}",
    arguments = listOf(
        navArgument("animation") {
            type = NavType.EnumType(ScreenAnimation::class)
            defaultValue = ScreenAnimation.VERTICAL // 默认使用底部滑入动画
            nullable = false
        }
    ),
    deepLinks = listOf(navDeepLink { 
        uriPattern = "myapp://test/details?animation={animation}" 
    }),
    enterTransition = {
        // 从目标页面参数中获取动画类型
        val animationType = targetState.arguments?.getSerializable("animation") 
            as? ScreenAnimation ?: ScreenAnimation.VERTICAL

        when (animationType) {
            ScreenAnimation.HORIZONTAL -> slideInHorizontally(
                initialOffsetX = { it },
                animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
            )
            ScreenAnimation.VERTICAL -> slideInVertically(
                initialOffsetY = { it },
                animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
            )
        }
    },
    exitTransition = { ExitTransition.None },
    popEnterTransition = { EnterTransition.None },
    popExitTransition = {
        // 从当前页面(即将弹出的页面)参数中获取动画类型
        val animationType = initialState.arguments?.getSerializable("animation") 
            as? ScreenAnimation ?: ScreenAnimation.VERTICAL

        when (animationType) {
            ScreenAnimation.HORIZONTAL -> slideOutHorizontally(
                targetOffsetX = { it },
                animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
            )
            ScreenAnimation.VERTICAL -> slideOutVertically(
                targetOffsetY = { it },
                animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
            )
        }
    }
) { backStackEntry ->
    // 若需在Composable中使用动画类型,可从backStackEntry获取
    // val animationType = backStackEntry.arguments?.getSerializable("animation") as ScreenAnimation
    MyComposable()
}

3. 不同场景下的导航调用

  • 普通场景(右侧滑入):
navController.navigate("Details?animation=${ScreenAnimation.HORIZONTAL.name}")
  • 通知跳转场景(底部滑入):
navController.navigate("Details?animation=${ScreenAnimation.VERTICAL.name}")
  • Deep Link跳转:
    使用带参数的URI即可,例如:myapp://test/details?animation=HORIZONTAL

关键说明

  • 路由参数会保留在回退栈中,返回时的动画会与进入时保持一致。
  • 枚举类型可避免字符串拼写错误,提升代码健壮性。
  • 若不需要对外暴露动画参数,也可通过ViewModel或CompositionLocal临时传递,但路由参数方式更可靠(支持进程恢复场景)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 12:45:38