Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BottomSheetDialogFragment - listen to dismissed by user event

How can I listen to a FINAL dismissal of a BottomSheetDialogFragment? I want to save user changes on the final dismissal only...

I tried following:

Method 1

This only fires, if the dialog is dismissed by swiping it down (not on back press or on touch outside)

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    Dialog d = super.onCreateDialog(savedInstanceState);
    d.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {

            BottomSheetDialog d = (BottomSheetDialog) dialog;   
            FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);

            BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
            behaviour.setState(BottomSheetBehavior.STATE_EXPANDED);
            behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                @Override
                public void onStateChanged(@NonNull View bottomSheet, int newState) {
                    if (newState == BottomSheetBehavior.STATE_HIDDEN)
                    {
                        // Bottom Sheet was dismissed by user! But this is only fired, if dialog is swiped down! Not if touch outside dismissed the dialog or the back button
                        Toast.makeText(MainApp.get(), "HIDDEN", Toast.LENGTH_SHORT).show();
                        dismiss();
                    }
                }

                @Override
                public void onSlide(@NonNull View bottomSheet, float slideOffset) {

                }
            });
        }
    });
    return d;
}

Method 2

This does not allow me to distinguish between a final dismissal and one that is coming from a screen rotation or activity recreation...

 @Override
public void onDismiss(DialogInterface dialog)
{
    super.onDismiss(dialog);
    // this works fine but fires one time too often for my use case, it fires on screen rotation as well, although this is a temporarily dismiss only
    Toast.makeText(MainApp.get(), "DISMISSED", Toast.LENGTH_SHORT).show();
}

Question

How can I listen to an event that indicates, that the user has finished the dialog?

like image 399
prom85 Avatar asked Nov 15 '16 18:11

prom85


3 Answers

Although all similar questions on SO suggest using onDismiss I think following is the correct solution:

@Override
public void onCancel(DialogInterface dialog)
{
    super.onCancel(dialog);
    Toast.makeText(MainApp.get(), "CANCEL", Toast.LENGTH_SHORT).show();
}

This fires if:

* the user presses back
* the user presses outside of the dialog

This fires NOT:

* on screen rotation and activity recreation

Solution

Combine onCancel and BottomSheetBehavior.BottomSheetCallback.onStateChanged like following:

public class Dailog extends BottomSheetDialogFragment
{
    @Override
    public void onCancel(DialogInterface dialog)
    {
        super.onCancel(dialog);
        handleUserExit();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Dialog d = super.onCreateDialog(savedInstanceState);
        d.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;
                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
                behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                    @Override
                    public void onStateChanged(@NonNull View bottomSheet, int newState) {
                        if (newState == BottomSheetBehavior.STATE_HIDDEN)
                        {
                            handleUserExit();
                            dismiss();
                        }
                    }

                    @Override
                    public void onSlide(@NonNull View bottomSheet, float slideOffset) {

                    }
                });
            }
        });
        return d;
    }

    private void handleUserExit()
    {
        Toast.makeText(MainApp.get(), "TODO - SAVE data or similar", Toast.LENGTH_SHORT).show();
    }
}
like image 54
prom85 Avatar answered Oct 20 '22 11:10

prom85


If you extended from BottomSheetDialogFragment() just override in your class

 override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        //Code here
    }

This will trigger when onBackPress and when you dismiss the dialog by clicking outside of it.

Make sure to NOT set your dialog as cancelable because this will not fire

like image 11
Gastón Saillén Avatar answered Oct 20 '22 10:10

Gastón Saillén


bottomSheetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
   @Override
   public void onDismiss(DialogInterface dialog) {
       toast("dismissed");
   }
});
like image 7
sharma.mahesh369 Avatar answered Oct 20 '22 12:10

sharma.mahesh369