DialogFragment 忽略 OnBackPressedDispatcher

Dav*_*ini 4 android android-fragments androidx

我正在尝试处理 a 中的后退按钮BottomSheetDialogFragment,即 a DialogFragment,使用'androidx.activity:activity-ktx:1.1.0-alpha01'and 'androidx.fragment:fragment-ktx:1.2.0-alpha01'

handleOnBackPressed()没有被调用并被DialogFragment解雇。在OnBackPressedCallback按下后退按钮时启用。

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

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

小智 17

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

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

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


Mih*_* Ya 7

另一种解决方案:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return super.onCreateDialog(savedInstanceState).also {
        val componentDialog = it as ComponentDialog
        componentDialog.onBackPressedDispatcher.addCallback(this) {
            val backPressedConsumed = yourLegacyLogic()
            if (backPressedConsumed.not()) {
                isEnabled = false
                requireActivity().onBackPressedDispatcher.onBackPressed()
                isEnabled = true
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

解释

后按事件会传递到 的 中dialogDialogFragment因此您应该OnBackpressedCallback注册dialog

禁用回调 ( isEnabled = false) 可以防止消耗下一个回按事件。一旦您禁用回调,您将重新触发后退按下事件(调用requireActivity().onBackPressed()),并且它将被其他人使用,例如您的导航将弹出后退堆栈。

之后,您应该启用回调(isEnabled = true)来接收下一个背按事件。


Dav*_*ini 3

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

创建自定义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()
    }
}
Run Code Online (Sandbox Code Playgroud)

还有它的interface

interface BackPressBottomSheetDialogCallback {
    fun shouldInterceptBackPress(): Boolean
    fun onBackPressIntercepted()
}
Run Code Online (Sandbox Code Playgroud)

然后在你的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)
}
Run Code Online (Sandbox Code Playgroud)