Android中DialogFragment dismiss前如何添加关闭确认拦截逻辑
问题原因
你将confirmCancel绑定到onCancelListener时,该回调的触发前提是系统已经执行了Dialog的取消流程,原DialogFragment已经被系统自动关闭,所以弹出确认弹窗时原窗口已消失,后续确认操作自然无效。
解决方案
我们可以禁用系统默认的自动关闭逻辑,自行捕获返回键、外部点击事件,统一走自定义的确认流程,仅在用户确认后主动调用dismiss关闭窗口。注意这里的禁用默认取消行为不是完全禁止关闭,只是拦截系统自动触发的关闭动作,所有关闭逻辑由你自行控制,符合条件性允许关闭的需求。
具体实现步骤
- 重写自定义DialogFragment的
onCreateDialog方法,拦截返回键和外部点击事件:
import android.app.Dialog; import android.graphics.Rect; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; // 替换为你的自定义DialogFragment类名 public class YourCustomDialogFragment extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { Dialog originalDialog = super.onCreateDialog(savedInstanceState); // 拦截返回键事件 originalDialog.setOnKeyListener((dialog, keyCode, event) -> { if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) { confirmCancel(); // 消费返回键事件,阻止系统默认关闭逻辑 return true; } return false; }); // 拦截外部点击事件 originalDialog.getWindow().getDecorView().setOnTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { Rect dialogRect = new Rect(); originalDialog.getWindow().getDecorView().getHitRect(dialogRect); // 判断点击位置是否在Dialog区域外 if (!dialogRect.contains((int) event.getX(), (int) event.getY())) { confirmCancel(); // 消费触摸事件,阻止系统默认关闭逻辑 return true; } } return v.onTouchEvent(event); }); return originalDialog; } // 原有的confirmCancel方法无需修改 public void confirmCancel() { new AlertDialog.Builder(getActivity()) .setIcon(R.drawable.ic_baseline_warning_24) .setTitle("Discard changes") .setMessage("Are you sure you want to discard changes and go back?") .setPositiveButton("Yes", (dialogInterface, i) -> dismiss()) .setNegativeButton("No", (dialogInterface, i) -> {}) .show() .setCanceledOnTouchOutside(true); } }
- 原有底部取消按钮的点击事件仍然绑定
confirmCancel即可,所有关闭入口的逻辑保持统一。
逻辑说明
- 所有触发关闭的操作(返回键、外部点击、底部取消按钮)都会先触发
confirmCancel弹出二次确认窗,此时原DialogFragment仍处于显示状态 - 用户点击确认才会主动调用
dismiss关闭原窗口,点击取消则回到原DialogFragment页面,完全符合需求。
内容的提问来源于stack exchange,提问作者Anchith Acharya
相关产品推荐
相关产品推荐

