How to handle back button when at the starting destination of the navigation component

MichaelThePotato picture MichaelThePotato · Jun 19, 2018 · Viewed 14.7k times · Source

I've started working with the new navigation component and I'm really digging it! I do have one issue though - How am I supposed to handle the back button when I'm at the starting destination of the graph?

This is the code I'm using now:

findNavController(this, R.id.my_nav_host_fragment)
                .navigateUp()

When I'm anywhere on my graph, it's working great, it send me back, but when I'm at the start of it - the app crashes since the backstack is empty.

This all makes sense to me, I'm just not sure how to handle it.

While I can check if the current fragment's ID is the same as the one that I know to be the root of the graph, I'm looking for a more elegant solution like some bool flag of wether or not the current location in the graph is the starting location or not.

Ideas?

Answer

John van den Berg picture John van den Berg · Oct 17, 2018

I had a similar scenario where I wanted to finish the activity when I was at the start destination and do a regular 'navigateUp' when I was further down the navigation graph. I solved this through a simple extension function:

fun NavController.navigateUpOrFinish(activity: AppCompatActivity): Boolean {
return if (navigateUp()) {
    true
} else {
    activity.finish()
    true
}

}

And then call it like:

override fun onSupportNavigateUp() = 
        findNavController(R.id.nav_fragment).navigateUpOrFinish(this)

However I was unable to use NavigationUI as this would hide the back arrow whenever I was at the start destination. So instead of:

NavigationUI.setupActionBarWithNavController(this, controller)

I manually controlled the home icon:

setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_navigation_back)