androidkotlinandroid-jetpack-composeandroid-jetpackandroid-jetpack-navigation

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


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


Solution

  • 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.