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

Android Compose导航:过渡动画无法获取导航参数问题排查

问题:Compose Navigation动画中无法获取导航参数,但Composable代码块中可正常获取

在使用Compose Navigation时,配置页面的enterTransition和exitTransition时,尝试通过initialState.arguments获取导航参数x、y,结果值为null;但在Composable的lambda代码块中通过it.arguments访问这些参数时,却能得到正确的值。

复现代码

composable(
    route = NavigationRoute.PreviewImage.route,
    deepLinks = listOf(navDeepLink { uriPattern = "suntuk://preview/{id}/{type}/{x}/{y}" }),
    arguments = listOf(
        navArgument("id") { type = NavType.StringType },
        navArgument("type") { type = NavType.IntType },
        navArgument("x") { type = NavType.FloatType },
        navArgument("y") { type = NavType.FloatType }
    ),
    enterTransition = {
        val offsetX = initialState.arguments?.getFloat("x") ?: 0f
        val offsetY = initialState.arguments?.getFloat("y") ?: 0f
        scaleIn(
            animationSpec = tween(durationMillis = 5000),
            transformOrigin = TransformOrigin(
                offsetX,
                offsetY
            )
        )
    },
    exitTransition = {
        val offsetX = initialState.arguments?.getFloat("x") ?: 0f
        val offsetY = initialState.arguments?.getFloat("y") ?: 0f
        Timber.i("Offset: $offsetX, $offsetY")
        scaleOut(
            animationSpec = tween(durationMillis = 5000),
            transformOrigin = TransformOrigin(
                offsetX,
                offsetY
            )
        )
    }
) {
    val id = it.arguments?.getString("id") ?: ""
    val type = it.arguments?.getInt("type") ?: 0
    val x = it.arguments?.getFloat("x") ?: 0f
    val y = it.arguments?.getFloat("y") ?: 0f
    Timber.i("Preview image: $id, $type, $x, $y")
    val viewModel: PreviewImageViewModel = koinViewModel { parameterSetOf(id, type) }

    PreviewImageScreen(
        viewModel = viewModel,
        onBack = {
            navController.navigateUp()
        }
    )
}

原因分析

核心差异在于代码的执行时机:

  • 动画配置块(enterTransition/exitTransition)的执行逻辑会在导航触发后立即启动,此时目标页面的initialState还未完成导航参数的绑定注入,所以arguments为空。
  • 而Composable的lambda代码块是在页面初始化渲染阶段执行的,此时导航参数已经完成绑定并注入到页面的arguments中,因此能正常获取到值。

解决方案

通过页面对应的navBackStackEntry获取参数即可解决。导航过程中,navBackStackEntry会提前持有完整的导航参数信息,不受页面参数绑定时机的影响:

修改动画配置代码如下:

enterTransition = {
    // 进入动画用targetState的navBackStackEntry,对应要打开的页面
    val navBackStackEntry = targetState.navBackStackEntry
    val offsetX = navBackStackEntry.arguments?.getFloat("x") ?: 0f
    val offsetY = navBackStackEntry.arguments?.getFloat("y") ?: 0f
    scaleIn(
        animationSpec = tween(durationMillis = 5000),
        transformOrigin = TransformOrigin(offsetX, offsetY)
    )
},
exitTransition = {
    // 退出动画用initialState的navBackStackEntry,对应要关闭的页面
    val navBackStackEntry = initialState.navBackStackEntry
    val offsetX = navBackStackEntry.arguments?.getFloat("x") ?: 0f
    val offsetY = navBackStackEntry.arguments?.getFloat("y") ?: 0f
    Timber.i("Offset: $offsetX, $offsetY")
    scaleOut(
        animationSpec = tween(durationMillis = 5000),
        transformOrigin = TransformOrigin(offsetX, offsetY)
    )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 15:36:01