How to handle back navigation with Jetpack Compose + Navigation (without fragments)

I am trying to navigate lets say from onboarding to dashboard and beyond and pop the onboarding once user hits dashboard, but still with 'back action' I end up on onboarding again.

Here is the sample code:

@AndroidEntryPoint class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MainUI() } } } 
@Composable fun MainUI() { val navController = rememberNavController() NavHost( navController = navController, startDestination = "onboarding" ) { composable("onboarding") { Column { Text("I am on onboarding") Button(onClick = { navController.navigate("dashboard") { popUpTo("dashboard") // I want to get rid of onboarding here } }) { Text("go to dashboard") } } } composable("dashboard") { Column { Text("I am on dashboard") Button(onClick = { navController.navigate("detail") }) { Text("go to detail") } } } composable("detail") { Text("I am on detail") } } } 

This doesn't work either

navController.navigate("dashboard") { popUpTo("dashboard") { inclusive = true // no difference } // .... popUpTo("onboarding") // also nothing // .... popUpTo("onboarding") { inclusive = true // this crashes -> NavGraph cannot be cast to ComposeNavigator$Destination } } 

For some reason this kind of works, so dashboard is dismissed and from detail I end up on onboarding 🤦

navController.navigate("detail") { popUpTo("dashboard") { inclusive = true } } 

4 Answers

I found my solution very easy, if I'm wrong please enlighten me.

navController.popBackStack() 
1

You can use BackHandler Link:

@Composable fun TestScreen() { BackHandler { // code // example - activity.finish() } } 
1

As @James Christian Kaguo already said navController.popBackStack() is an option. But you have to be careful when using this method. For some Reason the size of the BackQueue is at least 2 and if popping the backstack lower than that, navigation does not seem to work anymore.

Therefore I wrote following simple extension function:

fun NavController.navigateBack() { if (backQueue.size > 2) { popBackStack() } } 
1

Well, I've found working solution myself, still not sure if this "boilerplate code" is needed :( But this works as intended, means "page" is dismissed once navigated from it.

NavHost( navController = navController, startDestination = "onboarding" ) { navigation( startDestination = "onboardingUI", route = "onboarding" ) { composable("onboardingUI") { Column { Text("I am on onboarding") Button(onClick = { navController.navigate("dashboard"){ popUpTo("onboarding") } }) { Text("go to dashboard") } } } } navigation(startDestination = "dashboardUI", route = "dashboard") { composable("dashboardUI") { Column { Text("I am on dashboard") Button(onClick = { navController.navigate("detail"){ popUpTo("dashboard") } }) { Text("go to detail") } } } } navigation(startDestination = "detailUI", route = "detail") { composable("detailUI") { Text("I am on detail") } } } } 

NOTE: route and startDestination AKA name of the composable cannot be same

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

You Might Also Like