Navigation Compose animation is always using the default transition

1.4k views Asked by At

I just migrated to navigation compose version 2.7.3 and am trying to implement the new animations. My issue is the animations don't work on some of the screens and is always the default fade animation.

I've tried to update both the NavHost animations and each individual composable for enterTransition, exitTransition, popEnterTransition, popExitTransition but its still the default. Is there something I'm missing?

2

There are 2 answers

0
Megh Lath On

You can checkout this sample implementation(working proper for me)

First, define transitions like below:

private const val TIME_DURATION = 300

val enterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
    slideInHorizontally(
        initialOffsetX = { it },
        animationSpec = tween(durationMillis = TIME_DURATION, easing = LinearOutSlowInEasing)
    )
}

val exitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
    slideOutHorizontally(
        targetOffsetX = { -it / 3 },
        animationSpec = tween(durationMillis = TIME_DURATION, easing = LinearOutSlowInEasing)
    )
}

val popEnterTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition = {
    slideInHorizontally(
        initialOffsetX = { -it / 3 },
        animationSpec = tween(durationMillis = TIME_DURATION, easing = LinearOutSlowInEasing)
    )
}

val popExitTransition: AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition = {
    slideOutHorizontally(
        targetOffsetX = { it },
        animationSpec = tween(durationMillis = TIME_DURATION, easing = LinearOutSlowInEasing)
    )
}

@ExperimentalAnimationApi
fun NavGraphBuilder.slideComposable(
    route: String,
    arguments: List<NamedNavArgument> = emptyList(),
    content:
        @Composable()
        (AnimatedContentScope.(NavBackStackEntry) -> Unit)
) {
    composable(
        route,
        arguments = arguments,
        enterTransition = enterTransition,
        exitTransition = exitTransition,
        popEnterTransition = popEnterTransition,
        popExitTransition = popExitTransition,
        content = content
    )
}

And use slideComposable function instead of composable() inside NavGraph:

NavHost(
    navController,
    startDestination = "destination",
    modifier = Modifier) {
       navigation(startDestination = "startDestination", route = "route") {
          slideComposable("route) {
              /*Composable()*/
          }     
       }
}
0
Viktor Yakunin On

It's really easy nowadays, you can override animations for single destination or you can override for whole NavHost:

 NavHost(
    navController = navController,
    startDestination = Screen.MainScreen.route,
    enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, tween(700)) },
    exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, tween(700)) },
    popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, tween(700)) },
    popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, tween(700)) }
 ) {
    composable(Screen.MainScreen.route) {
        MainScreen(navController = navController)
    }

    composable(Screen.GameScreen.route) {
        GameScreen(navController = navController)
    }