Customise Back and Navigation Up action

 When you press the “Back” button, the screen of the app goes to the previous page(fragment or activity). However, if you want to have a custom behaviour (For example, pop up a dialog to ask the user to confirm again to exit when you are uploading something.) when you press the button. You can look at the steps below. 

You can also implement custom behaviour for the “navigation up” button of the Navigation component on the action bar.

Custom action for “back” button

In the Activity class or Fragment class, provide your Callback method(what you want to do when the user presses the ‘back’ button) to OnBackPressedDispatcher in the override onCreate() method.



OnBackPressedCallback callback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                // implement what you want to do for the back button event
            }
        };

@Override
public void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

       //for Fragment
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

//for Activity
//onBackPressedDispatcher.addCallback(this, callback);
}

After you finish the action and no longer need to perform the action, you can disable or remove the callback. Then, the “back” button will perform the normal “back” action.
callback.setEnabled(false);	// disable the callback
callback.remove();	//remove the callback
onBackPressed();	//call this method to invoke the normal "back" action programmatically

Custom action for “navigate up” on action bar

To customise the action, you are required to use action bar instead of toolbar. And Override OnSupportNavigateUp() method to implement the Navigate Up action.


AppBarConfiguration appBarConfiguration;

...

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...

    NavHostFragment navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment);
    NavController navController = navHostFragment.getNavController();
    appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
}

Then Override onSupportNavigateUp() to handle Up navigation.
@Override
public boolean onSupportNavigateUp() {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.navigateUp(navController, appBarConfiguration)
            || super.onSupportNavigateUp();
}

After you call NavigationUI.setupActionBarWithNavController() in activity, then you can set setHasOptionsMenu(true); and then overdrive onOptionItemSelected() method, the id of the “Up” button is android.R.id.home. Then implement your custom action inside.
@Override 
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
...
setHasOptionsMenu(true);
}

@Override 
public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
        case android.R.id.home: // Toolbar back button pressed, do something you want 
        default: 	return super.onOptionsItemSelected(item); 
    } 
}

For androidx.fragment:fragment:1.5.0-alpha04 or androidx.activity:activity:1.4.0-alpha01

setHasOptionsMenu(true) and onOptionsItemSelected() is deprecated. MenuHost interface is introduced.

In Activity, add MenuProvider and inflate the menu.

@Override
protected void onCreate(Bundle savedInstanceState) {
....
    // Add menu items without overriding methods in the Activity
    addMenuProvider(new MenuProvider() {
       @Override
       public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {
           menuInflater.inflate(R.menu.menu_main, menu);
       }

       @Override
       public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
       // Handle action bar item clicks here. The action bar will
       // automatically handle clicks on the Home/Up button, so long
       // as you specify a parent activity in AndroidManifest.xml.
           int id = menuItem.getItemId();
           if (id == R.id.action_settings) {
               return true;
           }
           return false;
       }
    });
}

In fragment, add MenuProvider and implement your action in onMenuItemSelected() method
public void onViewCreated(@NonNull View view, Bundle savedInstanceState)
    ....
    MenuHost menuHose = requireActivity();
    menuHose.addMenuProvider(new MenuProvider() {
       @Override
       public void onCreateMenu(@NonNull Menu menu, @NonNull MenuInflater menuInflater) {

       }

       @Override
       public boolean onMenuItemSelected(@NonNull MenuItem menuItem) {
           if(android.R.id.home == menuItem.getItemId()){
               // you action
           }
           return true;
       }
    }, getViewLifecycleOwner(), Lifecycle.State.RESUMED);
}

Reference

留言

此網誌的熱門文章

Use okhttp to download file and show progress bar

Download File into app specific storage with Retrofit

Unzipp file with Zip4j library