AlertDialog类用于显示对话框。关于AlertDialog的基本用法在这里就不详细介绍了,网上有很多,读者可以自己搜索。那么本文要介绍的是如何随心所欲地控制AlertDialog。
这里有两种修改方式:
方法一:
这种方法需要用点技巧。由于系统通过调用dismiss来关闭对话框,那么我们可以在dismiss方法上做点文章。在系统调用dismiss方法时会首先判断对话框是否已经关闭,如果对话框已经关闭了,就会退出dismiss方法而不再继续关闭对话框了。因此,我们可以欺骗一下系统,当调用dismiss方法时我们可以让系统以为对话框已经关闭(虽然对话框还没有关闭),这样dismiss方法就失效了,这样即使系统调用了dismiss方法也无法关闭对话框了。
下面让我们回到AlertDialog的源代码中,再继续跟踪到AlertDialog的父类Dialog的源代码中。找到dismissDialog方法。实际上,dismiss方法是通过dismissDialog方法来关闭对话框的,dismissDialog方法的代码如下:
private void dismissDialog() { if (mDecor == null ) { if (Config.LOGV) Log.v(LOG_TAG, " [Dialog] dismiss: already dismissed, ignore " ); return ; } if ( ! mShowing) { if (Config.LOGV) Log.v(LOG_TAG, " [Dialog] dismiss: not showing, ignore " ); return ; } mWindowManager.removeView(mDecor); mDecor = null ; mWindow.closeAllPanels(); onStop(); mShowing = false ; sendDismissMessage(); }
该方法后面的代码不用管它,先看 if(!mShowing){ … } 这段代码。这个 mShowing 变量就是判断对话框是否已关闭的。因此,我们在代码中通过设置这个变量就可以使系统认为对话框已经关闭,就不再继续关闭对话框了。由于 mShowing 也是 private 变量,因此,也需要反射技术来设置这个变量。我们可以在对话框按钮的单击事件中设置 mShowing ,代码如下:
try { Field field = dialog.getClass() .getSuperclass().getDeclaredField( "mShowing" ); field.setAccessible( true ); // 将mShowing变量设为false,表示对话框已关闭 field.set(dialog, false ); dialog.dismiss(); } catch (Exception e) { }
将上面的代码加到哪个按钮的单击事件代码中,哪个按钮就再也无法关闭对话框了。如果要关闭对话框,只需再将 mShowing 设为 true 即可。要注意的是,在一个按钮里设置了 mShowing 变量,也会影响另一个按钮的关闭对话框功能,因此,需要在每一个按钮的单击事件里都设置 mShowing 变量的值。
方法二:
现在我们来看看第一个需求:如果某个应用需要弹出一个对话框。当单击“确定“按钮时完成某些工作,如果这些工作失败,对话框不能关闭。而当成功完成工作后,则关闭对话框。当然,无论何程度情况,单击“取消”按钮都会关闭对话框。
这个需求并不复杂,也并不过分(虽然我们可以自己弄个Activity来完成这个工作,也可在View上自己放按钮,但这显示有些大炮打蚊子了,如果对话框上只有一行文本,费这么多劲太不值了)。但使用过AlertDialog的读者都知道,无论单击的哪个按钮,无论按钮单击事件的执行情况如何,对话框是肯定要关闭的。也就是说,用户无法控制对话框的关闭动作。实际上,关闭对话框的动作已经在Android SDK写死了,并且未给使用者留有任何接口。但我的座右铭是“宇宙中没有什么是不能控制的”。
既然要控制对放框的关闭行为,首先就得分析是哪些类、哪些代码使这个对话框关闭的。进入AlertDialog类的源代码。在AlertDialog中只定义了一个变量:mAlert。这个变量是AlertController类型。AlertController类是Android的内部类,在com.android.internal.app包中,无法通过普通的方式访问。也无法在Eclipse中通过按Ctrl键跟踪进源代码。但可以直接在Android源代码中找到AlertController.java。我们再回到AlertDialog类中。AlertDialog类实际上只是一个架子。象设置按钮、设置标题等工作都是由AlertController类完成的。因此,AlertController类才是关键。
找到AlertController.java文件。打开后不要感到头晕哦,这个文件中的代码是很多地。不过这么多代码对本文的主题也没什么用处。下面就找一下控制按钮的代码。
在AlertController类的开头就会看到如下的代码:
View.OnClickListener mButtonHandler = new View.OnClickListener() { public void onClick(View v) { Message m = null ; if (v == mButtonPositive && mButtonPositiveMessage != null ) { m = Message.obtain(mButtonPositiveMessage); } else if (v == mButtonNegative && mButtonNegativeMessage != null ) { m = Message.obtain(mButtonNegativeMessage); } else if (v == mButtonNeutral && mButtonNeutralMessage != null ) { m = Message.obtain(mButtonNeutralMessage); } if (m != null ) { m.sendToTarget(); } // Post a message so we dismiss after the above handlers are executed mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface) .sendToTarget(); } };
从这段代码中可以猜出来,前几行代码用来触发对话框中的三个按钮( Positive 、 Negative 和 Neutral )的单击事件,而最后的代码则用来关闭对话框(因为我们发现了 MSG_DISMISS_DIALOG 、猜出来的)。
mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface) .sendToTarget();
上面的代码并不是直接来关闭对话框的,而是通过一个 Handler 来处理,代码如下:
private static final class ButtonHandler extends Handler { // Button clicks have Message.what as the BUTTON{1,2,3} constant private static final int MSG_DISMISS_DIALOG = 1 ; private WeakReference < DialogInterface > mDialog; public ButtonHandler(DialogInterface dialog) { mDialog = new WeakReference < DialogInterface > (dialog); } @Override public void handleMessage(Message msg) { switch (msg.what) { case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEUTRAL: ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what); break ; case MSG_DISMISS_DIALOG: ((DialogInterface) msg.obj).dismiss(); } } }
从上面代码的最后可以找到 ((DialogInterface) msg.obj).dismiss();。现在看了这么多源代码,我们来总结一下对话框按钮单击事件的处理过程。在AlertController处理对话框按钮时会为每一个按钮添加一个onclick事件。而这个事件类的对象实例就是上面的mButtonHandler。在这个单击事件中首先会通过发送消息的方式调用为按钮设置的单击事件(也就是通过setPositiveButton等方法的第二个参数设置的单击事件),在触发完按钮的单击事件后,会通过发送消息的方式调用dismiss方法来关闭对话框。而在AlertController类中定义了一个全局的mHandler变量。在AlertController类中通过ButtonHandler类来对象来为mHandler赋值。因此,我们只要使用我们自己Handler对象替换ButtonHandler就可以阻止调用dismiss方法来关闭对话框。下面先在自己的程序中建立一个新的ButtonHandler类(也可叫其他的名)。
class ButtonHandler extends Handler { private WeakReference < DialogInterface > mDialog; public ButtonHandler(DialogInterface dialog) { mDialog = new WeakReference < DialogInterface > (dialog); } @Override public void handleMessage(Message msg) { switch (msg.what) { case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEUTRAL: ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog .get(), msg.what); break ; } } }
我们可以看到,上面的类和AlertController中的ButtonHandler类很像,只是支掉了switch语句的最后一个case子句(用于调用dismiss方法)和相关的代码。
下面我们就要为AlertController中的mHandler重新赋值。由于mHandler是private变量,因此,在这里需要使用Java的反射技术来为mHandler赋值。由于在AlertDialog类中的mAlert变量同样也是private,因此,也需要使用同样的反射技术来获得mAlert变量。代码如下:
先建立一个 AlertDialog 对象
AlertDialog alertDialog = new AlertDialog.Builder( this ) .setTitle( " abc " ) .setMessage( " content " ) .setIcon(R.drawable.icon) .setPositiveButton( “确定”, new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }).setNegativeButton( " 取消 " , new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).create()
上面的对话框很普通,单击哪个按钮都会关闭对话框。下面在调用 show 方法之前来修改一个 mHandler 变量的值, OK ,下面我们就来见证奇迹的时刻。
try { Field field = alertDialog1.getClass().getDeclaredField( " mAlert " ); field.setAccessible( true ); // 获得mAlert变量的值 Object obj = field.get(alertDialog1); field = obj.getClass().getDeclaredField( " mHandler " ); field.setAccessible( true ); // 修改mHandler变量的值,使用新的ButtonHandler类 field.set(obj, new ButtonHandler(alertDialog1)); } catch (Exception e) { } // 显示对话框 alertDialog.show();
我们发现,如果加上try catch语句,单击对话框中的确定按钮不会关闭对话框(除非在代码中调用dismiss方法),单击取消按钮则会关闭对话框(因为调用了dismiss方法)。如果去了try…catch代码段,对话框又会恢复正常了。
相关推荐
总结起来,要在Android中实现`AlertDialog`点击按钮后不关闭对话框的功能,关键在于延迟设置Positive按钮的点击事件,并在事件处理中控制对话框的关闭。通过这种方式,可以实现更复杂的交互逻辑,如用户输入验证,而...
`AlertDialog`是Android SDK提供的一种对话框组件,用于显示警告、确认或者简单的信息提示。本篇将详细介绍如何在Android中模仿iPhone的Alert样式来构建自定义的`AlertDialog`。 首先,我们了解`AlertDialog`的基本...
在Android开发中,DialogFragment是Google官方推荐用来展示对话框的一种方式,它相较于传统的AlertDialog有诸多优势。在本文中,我们将深入探讨DialogFragment的使用、优势以及如何解决屏幕旋转问题。 首先,...
本篇文章将详细介绍如何实现在`AlertDialog`中点击按钮但不使其消失的效果。 首先,我们需要理解`AlertDialog`的基本构建过程。通常,我们创建`AlertDialog`会使用`AlertDialog.Builder`,设置标题、内容视图、按钮...
在Android开发中,为了提供与iOS相似的用户体验,有时我们需要创建具有iPhone样式的对话框(AlertDialog)。本篇文章将深入探讨如何在Android中实现这样的效果,主要关注源码解析和技术细节。 首先,`AlertDialog`...
当宿主被销毁时,`AlertDialog`也会随之消失。如果需要在Activity的生命周期方法中处理`AlertDialog`,需要特别注意避免内存泄漏。 7. **其他功能** - 可以使用`setCancelable()`控制用户是否能通过点击对话框外部...
在Android系统中,AlertDialog是一个非常重要的组件,它用于展示给用户一些重要的信息或者需要用户做出选择的场景。这个压缩包“安卓Android源码——alertDialog对话框.zip”可能包含了一个关于如何理解和使用...
在Android中,可以通过设置`setCancelable(true)`来允许用户通过点击对话框外的区域或按下返回键来取消对话框。 进度对话框(ProgressDialog)在处理长时间运行的任务时非常有用,它可以向用户展示任务的进度,避免...
在Android应用开发中,有时会出现一个特定的问题,即当用户触摸到AlertDialog的边缘外部时,对话框会自动消失。这在用户体验上可能并不理想,尤其是在需要用户与对话框进行交互时。从Android 4.0(API Level 14)...
2. **Menu**:菜单在Android应用中用于展示可选择的选项,一般出现在屏幕顶部或者在按下设备的菜单键时弹出。它可以包含多个菜单项,每个菜单项都可以关联一个特定的操作。菜单在Android中的实现通常涉及到`...
在Android开发中,`AlertDialog`是一个非常常见的组件,它用于显示警告、确认或者询问用户的信息。这个`alertDialog.zip`文件包含的源码是关于如何在Android应用中使用`AlertDialog`进行交互的学习材料。让我们深入...
在Android开发中,`AlertDialog`是一种常见的用于向用户展示警告、确认或选择信息的弹出式对话框。然而,系统默认的`AlertDialog`样式可能无法满足所有设计需求,因此开发者通常需要对其进行自定义以实现更个性化的...
在Android中,`AlertDialog`是一种用于显示警告或确认消息的对话框,通常包含一个标题、消息文本和一个或多个操作按钮。默认情况下,`AlertDialog`具有Android原生的外观,但通过自定义布局和样式,我们可以改变其...
在Android应用开发中,自定义退出提示弹出框是一个常见的需求,它可以帮助用户在退出应用时得到明确的提示,提高用户体验。本篇文章将详细讲解如何实现这样一个功能。 首先,我们来了解一下`Dialog`和`PopupWindow`...
在Android开发中,`AlertDialog`是一个非常重要的组件,它用于向用户显示警告、确认或提供简单选择的对话框。`AlertDialog`的设计分为两种主要类型:布局窗口设计和非布局型窗口设计。这两种设计方法各有其特点,...
在Android开发中,`AlertDialog`和`PopupWindow`是两种常用的弹出式界面组件,用于在用户进行特定操作时提供额外的信息或者交互选项。这两者虽然都能实现类似的效果,但它们的设计理念、使用场景和功能特性有所不同...
在Android开发中,对话框(Dialog)是一种常见的用户交互组件,用于向用户显示临时信息或者进行简单的用户操作选择。这个“普通对话框源码.zip”文件包含的就是关于Android普通对话框的实现源代码,这对于理解和...
在Android开发中,`AlertDialog`是用户界面(UI)设计中的一个重要组件,它用于向用户显示重要的信息或者需要用户做出决策的情况。`AlertDialog`通常比普通的`Toast`更显眼,因为它会阻止用户与背景应用的交互,直到...
1. 确认对话框:包含“确定”和“取消”按钮,用于确认用户是否执行某个操作。通过`AlertDialog.Builder`的`setPositiveButton`和`setNegativeButton`设置。 2. 单选选择对话框:用户在多个选项中选择一项,通常用...
在Android开发中,Dialog对话框是一种非常常见的组件,它用于在主界面之上显示临时的通知或交互信息,而不中断用户对应用程序的主要操作。本资源“安卓Dialog对话框相关-androiddialog总结Dialog整理.rar”提供了...