Dynamically Change Navigation Animation - Jetpack Compose

451 views Asked by At

How can I change the navigation animation of the same destination when navigating in jetpack compose? For example, I want to show the screen horizontally from the right and other times I want that same screen to come vertically from the bottom (when clicking on a notification). I can't really do it using navController.navigate(route) because the route is defined on the same hierarchy as the enterTransition and exitTransition.

composable(
        route = "Details",
        deepLinks = listOf(navDeepLink { uriPattern = "myapp://test/details" }),
        enterTransition = {
                slideInVertically(
                    initialOffsetY = { it },
                    animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
                )
            }
        },
        exitTransition = {
            ExitTransition.None
        },
        popEnterTransition = {
            EnterTransition.None
        },
        popExitTransition = {
            slideOutVertically(
                targetOffsetY = { it },
                animationSpec = tween(durationMillis = 700, easing = LinearOutSlowInEasing)
            )
        },
    ) {
         MyComposable()
    }
2

There are 2 answers

1
Jan Itor On BEST ANSWER

You can create several routes for the same screen. Something like:

fun NavGraphBuilder.detailsH() {
    composable("detailsH", /* horizontal transition */) {
        DetailsScreen()
    }
}
fun NavGraphBuilder.detailsV() {
    composable("detailsV", /* vertical transition */) {
        DetailsScreen()
    }
}

NavHost(..) {
    composable("screenA"){
        ScreenA(
            onNavigateToDetails = { navController.navigate("detailsH") }
        )
    }
    composable("screenB"){
        ScreenB(
            onNavigateToDetails = { navController.navigate("detailsV") }
        )
    }
    detailsH()
    detailsV()
}

@Composable
fun ScreenA(
    onNavigateToDetails : () -> Unit,
) {}
0
Ori On

You can utilize navigation arguments. Once you have set up the navigation arguments, you can access the argument value and adjust the transition behavior. Here's an example:

NavHost(..) {
    composable(
        route = "Details/{MyAnimation}",
        enterTransition = {
            val slideDirection = this.targetState.arguments?.getString("MyAnimation") ?: "start"
            val slideDirectionEnum = when (slideDirection) {
                "slideUp" -> AnimatedContentTransitionScope.SlideDirection.up
                "slideDown" -> AnimatedContentTransitionScope.SlideDirection.down
                else -> AnimatedContentTransitionScope.SlideDirection.start // default
            }

            fadeOut(
                animationSpec = tween(
                    durationMillis = 300,
                    easing = LinearEasing
                )
            ) + slideOutOfContainer(
                animationSpec = tween(durationMillis = 300, easing = EaseOut),
                towards = slideDirection
            )
        },
    ){
        MyComposable()
    }
    composable("OtherComposable"){
        OtherComposableScreen(
            onNavigateToDetails = { navController.navigate("Details/slideUp") }
        )
    }
}