如何清理Jetpack Compose中重复的导航过渡代码?
问题场景
你的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
相关产品推荐
相关产品推荐

