DialogFragment 忽略 OnBackPressedDispatcher

DialogFragment ignores OnBackPressedDispatcher

我正在尝试使用 'androidx.activity:activity-ktx:1.1.0-alpha01''androidx.fragment:fragment-ktx:1.2.0-alpha01' 来处理 BottomSheetDialogFragment 中的后退按钮。

handleOnBackPressed() 未被调用,DialogFragment 被关闭。 OnBackPressedCallback 在按下后退按钮时启用。

我认为 DialogFragment 正在拦截后退按钮按下,因为 ComponentActivity 从不调用 mOnBackPressedDispatcher.onBackPressed();

有没有办法覆盖 DialogFragment 后退按钮按下处理?

我找到了解决方案,但我希望图书馆能处理这个用例。

创建自定义 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()
    }
}

及其interface

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

然后在你的 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)
}

真的很难理解 Google Android 开发者在做什么。无论如何,我找到了不使用接口的解决方案。

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

只需覆盖 onCreateDialog 并覆盖其中的 onBackPressed。

我的 Kotlin 解决方案:

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