Iscle
Iscle

Reputation: 829

Intercept back navigation with Android Navigation Component

I'm trying to intercept the back navigation on an Android app to run some code before exiting the current fragment/activity.

The app is using Android Navigation Component, hooked up to a bottom navigation bar and a toolbar. The toolbar will show the back button when the stack is not empty.

What I'm trying to achieve is to show a custom dialog before exiting the fragment, asking the user if they want to save the data or not. My fragment contains a few EditText fields and a save button, that should be pressed to save the data to the repository. In case the user does not do this, then the popup should be shown when going back.

I've managed to intercept the android back button using a "OnBackPressedCallback", but the toolbar back button will still close the fragment.

Is there any way to intercept both methods (going back from the toolbar button, and with the android back button)?

Thanks

Upvotes: 3

Views: 1189

Answers (3)

Romain Scherfflein
Romain Scherfflein

Reputation: 175

I had a similar problem but additionally i have a Drawer menu in my setup. And i needed to intercept the UP navigation action in one certain fragment only. Additionally it turned out that once you add the NavigationOnCLickListener you will never get rid of it. So this was no option.

What worked for me succesfully was to set the toolbar as SupportActionBar after all the navigation stuff was done.

Now the UP action event appeared in onOptionItemSelected() and here i can use NavController.currentDestination to check on which Fragment i currently am and i can chose here whether i open the drawer, navigate up (or somewhere else) or simply do nothing.

// in Activity.onCreate()
// do your setup of Navigation UI

setSupportActionBar(toolbar)

// add (it won't work without)

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        return super.onCreateOptionsMenu(menu)
}

// and then

override fun onOptionsItemSelected(item: MenuItem): Boolean {

        when (navController?.currentDestination?.id) {
            R.id.dontAllowUpNavigationFragment -> { }
            in topLevelDestinationIds -> { binding.drawerLayout.open() }
            else -> { navController?.navigateUp() }
        }
        return true
    }

Upvotes: 1

Happo
Happo

Reputation: 1397

You can look in the code of NavigationUI.setupWithNavController( toolbar, navController, appBarConfiguration ) which show you how the up navigation is implemented for the toolbar.

Here is my solution:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    // default toolbar setup with navigation components
    final NavController navController = Navigation.findNavController( view );
    final AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder( navController.getGraph() ).build();
    NavigationUI.setupWithNavController( toolbar, navController, appBarConfiguration );

    // own changes like icon and dialog
    toolbar.setNavigationIcon( R.drawable.ic_close_24 );
    toolbar.setNavigationOnClickListener( v -> new AlertDialog.Builder( requireContext() )
        .setMessage( R.string.abort_editing )
        .setPositiveButton( R.string.dialog_button_close, (dialog, whichButton) -> NavigationUI.navigateUp( navController, appBarConfiguration ) )
        .setNegativeButton( R.string.dialog_button_cancel, null )
        .show() );
}

Upvotes: 3

nsk
nsk

Reputation: 330

Have you tried to use navigation listener on toolbar?

https://developer.android.com/reference/android/widget/Toolbar#setNavigationOnClickListener(android.view.View.OnClickListener)

You have to handle both cases separately, there is no single method for this case.

Upvotes: 2

Related Questions