How to add a Listener and Receive a callback whenever the navigation transition has finished in Jetpack Compose (NavHostController)?
E

2

11

I am trying to add a Listener and receive a callback whenever the navigation transition has finished in Jetpack Compose.

I have tried to use the NavController API addOnDestinationChangedListener but it is send immediately to my listener and is not waiting for the composition to finish.


val navController = rememberNavController()

// Register the destination changed listener
navController.addOnDestinationChangedListener { _, destination, _ ->
    // destination change is sent immediately and isnt waiting for the composable to finish
}

My goal is to add a listener that is only fired once the composition is completed and the destination is changed.

something like this:

// Register the transition finished listener
navController.transitionFinished{ _, destination ->
    // Do something when the navigation transition has finished
}

    NavHost(navController = navController, startDestination = "Home") {
        composable("Home") { 
            // THE CALLBACK IS FIRED HERE, IMMEDITIETLY
            Text("FIRST SITE")
            //FIRE NOW THE CALLBACK AFTER IT FINISHED COMPOSITION
        }
        composable("Settings") {
            // THE CALLBACK IS FIRED HERE, IMMEDITIETLY
            Text("SECOND SITE")
            //FIRE NOW THE CALLBACK AFTER IT FINISHED COMPOSITION
        }
    }

Where it will only fire callback once the whole composable is finished its composition.

Are there options to get the current tranistioning state of the navHost so I can implement it myself or any other API calls I can use?

EDIT1: TO Clarify: I define finishing composition as the whole transition animation is finished

Eyestalk answered 21/12, 2022 at 9:47 Comment(2)
This issue exists in the AndroidX navigation graph as well and I am also interested in finding a solution to it. Perhaps a callback/lambda in the navigate() to be called when the destination is created/reachedGrandstand
This answer seems to be similar to what I saidGrandstand
G
4

I had the same problem but not with the compose. I used addOnDestinationChangedListener to change the title but the title was always updated before the destination was shown. But eventually I fixed it as follows:

navController.addOnDestinationChangedListener { controller, destination, args ->
    view?.post{
        title = destination.lable
    }
}

The view here is the rootView of your hosting view which can be an activity, fragment or dialog. Post function will make sure that the root view is fully loaded including the destination before executing the runnable passed in to it. you can use args or label in you navigation graph to pass on the name.

Grandstand answered 1/11, 2023 at 13:52 Comment(0)
W
8

I'm a bit confused by your code because it seems you are mixing classic AndroidX Navigation (findNavController()) and Navigation Compose here.

Here's a full Compose example of what you want to achieve:

val navController = rememberNavController()
val currentBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute by remember { derivedStateOf { currentBackStackEntry?.destination?.route ?: "Home" } }

NavHost(
  navController = navController,
  startDestination = "Home",
) {
  ...
}

The value of currentRoute contains the current route of the NavController and since it's a State it automatically updates when the destination changes.

Wendolyn answered 5/1, 2023 at 11:3 Comment(2)
This updates right when the route changes, and does not wait for the animation of the new screen to finishForebode
@Forebode Unfortunately I currently don't know a solution to this.Wendolyn
G
4

I had the same problem but not with the compose. I used addOnDestinationChangedListener to change the title but the title was always updated before the destination was shown. But eventually I fixed it as follows:

navController.addOnDestinationChangedListener { controller, destination, args ->
    view?.post{
        title = destination.lable
    }
}

The view here is the rootView of your hosting view which can be an activity, fragment or dialog. Post function will make sure that the root view is fully loaded including the destination before executing the runnable passed in to it. you can use args or label in you navigation graph to pass on the name.

Grandstand answered 1/11, 2023 at 13:52 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.