简体   繁体   中英

OnBackPressedCallback not called in Bottom Sheet Dialog Fragment

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)

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.

@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;
}

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
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM