android-fragments 未在底部工作表对话框片段中调用OnBackPressedCallback

rur96b6h  于 2022-11-14  发布在  Android
关注(0)|答案(3)|浏览(154)

我有一个Bottom Sheet Dialog Fragment,其中包含四个FragmentViewPager。我想在Bottom Sheet Dialog Fragment中单击onBackPressed时调用一个方法。在我的OnCreateView中实现了OnBackPressedCallback,但它没有被触发。有人知道为什么它没有被调用吗?

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)
ma8fv8wu

ma8fv8wu1#

我在寻找DialogFragment中存在的相同问题的解决方案时发现了这个线程。答案在上面的注解中,但为了完整起见,这里是汇总的信息:

解决方案

在你的DialogFragment中重写onCreateDialog并设置一个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
            }
        }
    }

说明

来自针对requireActivity().onBackPressedDispatcher.addCallback不适用于DialogFragments(https://issuetracker.google.com/issues/149173280)而提出的问题:
对话框是独立的窗口,始终位于Activity的窗口上方。这意味着,无论底层FragmentManager处于何种状态,或者您在Activity的onBackPressed()中运行何种代码,对话框都将继续拦截系统后退按钮--OnBackPressedDispatcher就是在这里插入的。
从本质上讲,当使用任何利用对话框的组件时,onBackPressedDispatcher是错误的工具,因为它们在应用程序中的行为方式和存在于活动之外(顶部)的方式不同。

wooyq4lh

wooyq4lh2#

@ITJscott解释得很好。如果有人在理解/实现Kotlin代码方面遇到困难,这里是相同的JAVA代码片段。

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

2j4z5cfb3#

如果您已使用将底部表单设置为不可取消,也会发生此行为。
因此,为了避免这种情况,您可以使用下面的代码来检测某些事件,如键盘输入或按下按钮。如果您想对其他事件执行其他操作,您可以在此处添加代码。

bottomSheetDialog.setOnKeyListener { _, keyCode, _ ->
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            onBackPressed()
            return@setOnKeyListener true
        } else {
            return@setOnKeyListener false
        }
    }

相关问题