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

如何清理Jetpack Compose中重复的导航过渡代码?

优化Jetpack Compose NavHost重复的路由转场动画代码

问题场景

你的NavHost中多个路由的enterTransition、exitTransition、popEnterTransition和popExitTransition逻辑完全重复,尝试提取普通函数复用时报错:Unresolved reference: slideIntoContainer。

错误原因

slideIntoContainer、slideOutOfContainer是AnimatedContentTransitionScope的成员函数,普通函数没有该作用域的上下文,因此无法直接调用这些方法。

优化方案

方案1:定义AnimatedContentTransitionScope扩展函数

将转场逻辑封装为AnimatedContentTransitionScope的扩展函数,这样就能在转场lambda的作用域内直接调用:

import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.slideIntoContainer
import androidx.compose.animation.slideOutOfContainer
import androidx.compose.animation.tween

// 复用转场逻辑的扩展函数
fun AnimatedContentTransitionScope.defaultEnterTransition() = slideIntoContainer(
    AnimatedContentTransitionScope.SlideDirection.Left,
    tween(500)
)

fun AnimatedContentTransitionScope.defaultExitTransition() = slideOutOfContainer(
    AnimatedContentTransitionScope.SlideDirection.Left,
    tween(500)
)

fun AnimatedContentTransitionScope.defaultPopEnterTransition() = slideIntoContainer(
    AnimatedContentTransitionScope.SlideDirection.Right,
    tween(500)
)

fun AnimatedContentTransitionScope.defaultPopExitTransition() = slideOutOfContainer(
    AnimatedContentTransitionScope.SlideDirection.Right,
    tween(500)
)

在NavHost中使用:

NavHost(
    navController = navController,
    startDestination = CreateProjectRoute,
) {
    composable<ProjectsListRoute>(
        enterTransition = { defaultEnterTransition() },
        exitTransition = { defaultExitTransition() },
        popEnterTransition = { defaultPopEnterTransition() },
        popExitTransition = { defaultPopExitTransition() }
    ) {
        ProjectsListScreen(
            onCreateButtonClicked = {
                navController.navigate(CreateProjectRoute)
            }
        )
    }
    composable<CreateProjectRoute>(
        enterTransition = { defaultEnterTransition() },
        exitTransition = { defaultExitTransition() },
        popEnterTransition = { defaultPopEnterTransition() },
        popExitTransition = { defaultPopExitTransition() }
    ) {
        CreateProjectScreen(
            viewModel = projectViewModel,
            navController = navController
        )
    }
}

方案2:封装自定义Composable扩展(更简洁)

如果所有路由的转场逻辑完全一致,可以直接封装一个带默认转场的自定义composable扩展,进一步简化代码:

import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.slideIntoContainer
import androidx.compose.animation.slideOutOfContainer
import androidx.compose.animation.tween
import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable

// 针对类型安全路由的自定义扩展
inline fun <reified T : NavRoute> NavGraphBuilder.defaultComposable(
    content: @Composable () -> Unit
) {
    composable<T>(
        enterTransition = {
            slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Left, tween(500))
        },
        exitTransition = {
            slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Left, tween(500))
        },
        popEnterTransition = {
            slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Right, tween(500))
        },
        popExitTransition = {
            slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Right, tween(500))
        },
        content = content
    )
}

使用时只需调用自定义扩展:

NavHost(
    navController = navController,
    startDestination = CreateProjectRoute,
) {
    defaultComposable<ProjectsListRoute> {
        ProjectsListScreen(
            onCreateButtonClicked = {
                navController.navigate(CreateProjectRoute)
            }
        )
    }
    defaultComposable<CreateProjectRoute> {
        CreateProjectScreen(
            viewModel = projectViewModel,
            navController = navController
        )
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 11:12:27