我有一个
Bottom Sheet Dialog Fragment
,其中包含四个 Fragment
和 ViewPager
。
我想在 onBackPressed
点击 Bottom Sheet Dialog Fragment
时调用一个方法。在我的 OnBackPressedCallback
中实现了 OnCreateView
但未触发。有人知道为什么不调用它吗?
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)
我在寻找 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):
对话框是独立的窗口,始终位于活动窗口上方。这意味着无论底层 FragmentManager 处于什么状态,或者您在 Activity 的 onBackPressed() 中运行什么代码(OnBackPressedDispatcher 插入的位置),对话框都将继续拦截系统后退按钮。
本质上,当使用任何使用对话框的组件时,
onBackPressedDispatcher
是错误的工具,因为它们在应用程序中的行为方式以及存在于活动之外(之上)。
@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;
}
如果您使用 将底部工作表设置为不可取消,也会发生此行为。
因此,为了避免这种情况,您可以使用下面的代码来检测某些事件,例如键盘输入或后按。如果您想对其他事件执行其他操作,您可以在此处添加代码。
bottomSheetDialog.setOnKeyListener { _, keyCode, _ ->
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed()
return@setOnKeyListener true
} else {
return@setOnKeyListener false
}
}
只要这样做,您的后退按钮事件就可以正常工作
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return object : Dialog(requireActivity(),R.style.BottomSheetDialogTheme){
override fun onBackPressed() {
backConfirmationPopup()
}
}
}