Search code examples
androidandroid-fragmentsandroid-lifecycleandroid-eventonbackpressed

How to do onBackPress dialog in fragment in android?


I was working on create a dialog that pop up to confirm whether the user exit the page.

In the past I used the activity so it has no problem. I just need to put the dialog inside the override onBackPress function, and call finish() if the user choose to leave.

However , currently I would like to switch the class to fragment inside a tabhost. So not only I need to handle the onbackpress but also the case when user click on the Tab bar to switch to other tab.

I tried:

@Override
public void onDetach() {
    AlertDialog.Builder builder = new Builder(ctx);
    builder.setMessage(getResources().getString(R.string.quit_form));
    builder.setNegativeButton(getResources().getString(R.string.yes),
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    File directory = new File(Constant.upload_imageFolder);
                    File[] files = directory.listFiles();
                    for (int i = 0; i < files.length; ++i) {
                        files[i].delete();
                    }
                    UploadForm.super.onDetach();
                }
            });
    builder.setPositiveButton(getResources().getString(R.string.no),
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    builder.create().show();
}

but it crash. How to fix the problem ? And is the onDetach correct function to override? Thanks a lot.

Update: The exception when ondetach:

android.support.v4.app.SuperNotCalledException: Fragment UploadForm{42db9eb0 #3 id=0x7f050075} did not call through to super.onDetach()

Solution

  • You need to Override onBackPressed() in the Activity. and make all the FragmentTransaction are addToBackStack before commit.

     @Override public void onBackPressed() {
         int count = getFragmentManager().getBackStackEntryCount();
    
         if (count == 0) {
             super.onBackPressed();
             //additional code
         } else {
             getFragmentManager().popBackStack();
         }
     }
    

    While the above approach would work for all fragments added to back stack . You can also customize it to follow a pattern.

    1. Create an interface such as BackNavigable (implemented by those fragments who would like to consume back press) , with a method boolean consumeBackPress();
    2. For those fragments who would like to consume back press event return true from the implementation.
    3. Now inside activity onBackPressed() peek the current fragment and check if that fragment is instance of BackNavigable and has return true in its consumeBackPress() implementation , If yes then pop that fragment otherwise call super.onBackPressed() of activity.

    That's all.