Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DialogFragment ignores OnBackPressedDispatcher

I'm trying to handle the back button in a BottomSheetDialogFragment, which is a DialogFragment, using 'androidx.activity:activity-ktx:1.1.0-alpha01' and 'androidx.fragment:fragment-ktx:1.2.0-alpha01'.

handleOnBackPressed() is not called and the DialogFragment is dismissed. The OnBackPressedCallback is enabled when the back button is pressed.

I think the DialogFragment is intercepting the back button press, because the ComponentActivity never calls mOnBackPressedDispatcher.onBackPressed();

Is there a way to override the DialogFragment handling of back button press?

like image 640
David Corsalini Avatar asked Jul 23 '19 08:07

David Corsalini


3 Answers

It's really hard to understand what Google Android Dev making. Anyway, i found a solution without using interfaces.

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return object : Dialog(requireContext(), theme) {
        override fun onBackPressed() {
            // handle back press
        }
    }
}

Just override the onCreateDialog and also override onBackPressed inside it.

like image 79
Mücahid Kambur Avatar answered Nov 14 '22 01:11

Mücahid Kambur


I found a solution, but I hope the library will take care of this usecase.

Create a custom BottomSheetDialog:

class BackPressBottomSheetDialog(context: Context, @StyleRes theme: Int, 
private val callback: BackPressBottomSheetDialogCallback) :
        BottomSheetDialog(context, theme) {

    override fun onBackPressed() {
        if (callback.shouldInterceptBackPress()) callback.onBackPressIntercepted()
        else super.onBackPressed()
    }
}

And its interface

interface BackPressBottomSheetDialogCallback {
    fun shouldInterceptBackPress(): Boolean
    fun onBackPressIntercepted()
}

Then in your BottomSheetDialogFragment

private val dialogCallback = object : BackPressBottomSheetDialogCallback {
      override fun shouldInterceptBackPress(): Boolean {
        //TODO should you intercept the back button?
      }

      override fun onBackPressIntercepted() {
        //TODO what happens when you intercept the back button press
      }
}

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return BackPressBottomSheetDialog(requireContext(), theme, dialogCallback)
}
like image 21
David Corsalini Avatar answered Nov 14 '22 02:11

David Corsalini


My solution for Kotlin:

Override below method in BottomSheetDialogFragment.

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 code
                // return true if you want keep dialog visible
                // return false if you want to dismiss dialog anyway
                return@setOnKeyListener true
            }
            return@setOnKeyListener false
        }
    }
}
like image 27
Kacper Dziubek Avatar answered Nov 14 '22 00:11

Kacper Dziubek