OnBackPressedCallback not called in Bottom Sheet Dialog Fragment
Asked Answered
D

3

12

I have a Bottom Sheet Dialog Fragment which contains four Fragment with ViewPager. I want to call a method when onBackPressed clicked in Bottom Sheet Dialog Fragment. Implemented OnBackPressedCallback in my OnCreateView but it is not triggered. Any one have a idea why it is not called?

val callback = object : OnBackPressedCallback(true */ true means that the callback is enabled /*) {
    override fun handleOnBackPressed() {
        // Show your dialog and handle navigation
        LogUtils.d("Bottom Sheet -> Fragment BackPressed Invoked")
    }
}

// note that you could enable/disable the callback here as well by setting callback.isEnabled = true/false
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
Donata answered 30/1, 2020 at 9:4 Comment(9)
developer.android.com/reference/androidx/activity/…Shelashelagh
@Shelashelagh I read it but not working even if I put it in onAttachDonata
Try putting it in onActivityCreated(). Also try using this instead of viewLifecycleOwnerFazio
@JemshitIskenderov still same, nothing happens :(Donata
Check if there is other fragments catching backpress before this one. And also check if Activity overrides onBackPressedFazio
I am having the same issue in a DialogFrament but it works in a normal Fragment. Were you able to resolve it @DonataChancemedley
Unfortunately not @ChancemedleyDonata
quite unfortunate. I have opened an issue here issuetracker.google.com/issues/149173280Chancemedley
I was able to work around this by overriding onKeyEvent: https://mcmap.net/q/209358/-detect-back-button-but-don-39-t-dismiss-dialogfragmentEating
C
18

I found this thread while looking for a solution to the same problem that exists in DialogFragment. The answers are in the comments above, but for completeness here is the information aggregated:

Solution

In your DialogFragment override onCreateDialog and set an OnKeyListener:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return super.onCreateDialog(savedInstanceState).apply {
            setOnKeyListener { _: DialogInterface, keyCode: Int, keyEvent: KeyEvent ->
                if (keyCode == KeyEvent.KEYCODE_BACK && keyEvent.action == KeyEvent.ACTION_UP) {

                    // <-- Your onBackPressed logic here -->

                    return@setOnKeyListener true
                }
                return@setOnKeyListener false
            }
        }
    }

Explanation

From an issue raised against requireActivity().onBackPressedDispatcher.addCallback not working for DialogFragments (https://issuetracker.google.com/issues/149173280):

Dialogs are separate windows that always sit above your activity's window. This means that the dialog will continue to intercept the system back button no matter what state the underlying FragmentManager is in, or what code you run in your Activity's onBackPressed() - which is where the OnBackPressedDispatcher plugs into.

Essentially the onBackPressedDispatcher is the wrong tool for the job when using any component that utilises Dialogs because of how they behave within an Application and exist outside (on top) of Activities.

Cheekbone answered 11/2, 2021 at 15:53 Comment(0)
A
0

@ITJscott has explained very well. in case any one struggling in understanding/ implementing kotlin code here is JAVA code snippet for the same.

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
    Dialog mDialog = super.onCreateDialog(savedInstanceState);
    mDialog.setOnKeyListener((dialog, keyCode, event) -> {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {

            // <-- Your onBackPressed logic here -->
            requireActivity().onBackPressed();
            return true;
        }
        return false;
    });
    return mDialog;
}
Alexisaley answered 20/6, 2022 at 11:29 Comment(0)
Q
0

This behaviour can also occur if you've set bottom sheet to be non-cancelable using .

So, to avoid this, you can use below code which detects certain events like keypad entry or back press. If you want to perform other action on other events, you can add the code here.

bottomSheetDialog.setOnKeyListener { _, keyCode, _ ->
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            onBackPressed()
            return@setOnKeyListener true
        } else {
            return@setOnKeyListener false
        }
    }
Quenchless answered 9/8, 2022 at 11:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.