如何在Jetpack Compose中实现屏幕间流畅的导航动画过渡?
Jetpack Compose 导航动画修复方案
问题描述
在Jetpack Compose应用中构建导航流程时,从StartScreen导航至LoginScreen时,StartScreen会覆盖LoginScreen,无法实现目标的屏幕间流畅滑动过渡(目标效果:StartScreen向左完全滑出,LoginScreen从右侧同步滑入)。调整initialOffset数值后仍未解决问题。
当前代码实现
@Composable fun MyAppNavigation( modifier: Modifier, authViewModel: AuthViewModel ) { val navController = rememberNavController() NavHost(navController = navController, startDestination = "start") { composable(route = "start", enterTransition = { slideInHorizontally( initialOffsetX = { -500 }, // small slide 300px animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing // interpolator ) ) }, exitTransition = { slideOutHorizontally( targetOffsetX = { -500 }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }) { StartPage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } composable(route = "login", enterTransition = { slideInHorizontally( initialOffsetX = { it }, // it == fullWidth animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }, exitTransition = { slideOutHorizontally( targetOffsetX = { it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) } ) { LoginPage( modifier = Modifier.fillMaxSize(), navController = navController, authViewModel = authViewModel ) } composable("signup") { SignupPage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } composable("home") { HomePage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } } }
修复方案
问题核心是当前StartScreen的退出动画未完全滑出屏幕,且未配置返回导航时的对应动画。调整动画参数并补充双向导航的动画逻辑即可解决:
@Composable fun MyAppNavigation( modifier: Modifier, authViewModel: AuthViewModel ) { val navController = rememberNavController() NavHost(navController = navController, startDestination = "start") { composable( route = "start", // 从Login返回Start时:从左侧滑入 enterTransition = { slideInHorizontally( initialOffsetX = { -it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }, // 从Start导航到Login时:向左完全滑出屏幕 exitTransition = { slideOutHorizontally( targetOffsetX = { -it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }, // 返回时Login的退出动画 popExitTransition = { slideOutHorizontally( targetOffsetX = { it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) } ) { StartPage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } composable( route = "login", // 从Start导航到Login时:从右侧滑入 enterTransition = { slideInHorizontally( initialOffsetX = { it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }, // 从Login导航到其他页面时:向右滑出 exitTransition = { slideOutHorizontally( targetOffsetX = { it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) }, // 返回时Start的进入动画 popEnterTransition = { slideInHorizontally( initialOffsetX = { -it }, animationSpec = tween( durationMillis = 1000, easing = FastOutSlowInEasing ) ) } ) { LoginPage( modifier = Modifier.fillMaxSize(), navController = navController, authViewModel = authViewModel ) } composable("signup") { SignupPage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } composable("home") { HomePage( modifier = modifier, navController = navController, authViewModel = authViewModel ) } } }
关键修改点
- StartScreen退出动画:将
targetOffsetX从固定值-500改为{ -it },让页面完全滑出屏幕左侧,避免覆盖LoginScreen。 - 补充返回动画配置:通过
popEnterTransition和popExitTransition定义返回导航时的动画逻辑,保证双向导航都有流畅过渡。 - 对齐动画方向:导航到Login时,Start左滑退出、Login右滑进入;返回时,Login右滑退出、Start左滑进入,完全匹配目标效果。
内容的提问来源于stack exchange,提问作者Fatima Jamal
相关产品推荐
相关产品推荐

