Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 222
MichaelThePotato Avatar asked Jun 19 '18 21:06

MichaelThePotato


People also ask

What happens when back button is pressed in Android?

Once you press the back key the activity's onDestroy() method will be called and the activity will be flushed out of the memory. You will then be required to restart the activity by calling the startActivity() method which will in turn call its onCreate() Method.

How does the Android back button work?

Up and Back are identical within your app's taskWhen you press the Back button, the current destination is popped off the top of the back stack, and you then navigate to the previous destination. The Up button appears in the app bar at the top of the screen.

How do I disable back press in fragment?

Here is the new way you can manage your onBackPressed() in fragment with the new call back of activity: // Disable onBack click requireActivity(). onBackPressedDispatcher. addCallback(this) { // With blank your fragment BackPressed will be disabled. }


2 Answers

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)
like image 158
John van den Berg Avatar answered Sep 20 '22 11:09

John van den Berg


Override onBackPressed in your activity and check if the current destination is the start destination or not.

Practically it looks like this:

@Override
public void onBackPressed() {
    if (Navigation.findNavController(this,R.id.nav_host_fragment)
            .getCurrentDestination().getId() == R.id.your_start_destination) {
        // handle back button the way you want here
        return;
    }
    super.onBackPressed();
}
like image 24
Shynline Avatar answered Sep 21 '22 11:09

Shynline