alertdialogandroid alertdialog怎样使用

alertdialog  时间:2021-07-22  阅读:()

Android系统怎么利用利用Java反射技术阻止通过按钮关闭对话框(AlertDialog)

众所周知,AlertDialog类用于显示对话框。

关于AlertDialog的基本用法在这里就不详细介绍了,网上有很多,读者可以自己搜索。

那么本文要介绍的是如何随心所欲地控制AlertDialog。

现在我们来看看第一个需求:如果某个应用需要弹出一个对话框。

当单击“确定“按钮时完成某些工作,如果这些工作失败,对话框不能关闭。

而当成功完成工作后,则关闭对话框。

当然,无论何程度情况,单击“取消”按钮都会关闭对话框。

这个需求并不复杂,也并不过分(虽然我们可以自己弄个Activity来完成这个工作,也可在View上自己放按钮,但这显示有些大炮打蚊子了,如果对话框上只有一行文本,费这么多劲太不值了)。

但使用过AlertDialog的读者都知道,无论单击的哪个按钮,无论按钮单击事件的执行情况如何,对话框是肯定要关闭的。

也就是说,用户无法控制对话框的关闭动作。

实际上,关闭对话框的动作已经在Android SDK写死了,并且未给使用者留有任何接口。

但我的座右铭是“宇宙中没有什么是不能控制的”。

既然要控制对放框的关闭行为,首先就得分析是哪些类、哪些代码使这个对话框关闭的。

进入AlertDialog类的源代码。

在AlertDialog中只定义了一个变量:mAlert。

这个变量是AlertController类型。

AlertController类是Android的内部类,.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 " ); essible( true ); // 获得mAlert变量的值 Object obj = field.get(alertDialog1); field = obj.getClass().getDeclaredField( " mHandler " ); essible( true ); // 修改mHandler变量的值,使用新的ButtonHandler类 field.set(obj, new ButtonHandler(alertDialog1)); } catch (Exception e) { } // 显示对话框 alertDialog.show();

我们发现,如果加上try catch语句,单击对话框中的确定按钮不会关闭对话框(除非在代码中调用dismiss方法),单击取消按钮则会关闭对话框(因为调用了dismiss方法)。

如果去了try…catch代码段,对话框又会恢复正常了。

虽然上面的代码已经解决了问题,但需要编写的代码仍然比较多,为此,我们也可采用另外一种方法来阻止关闭对话框。

这种方法不需要定义任何的类。

这种方法需要用点技巧。

由于系统通过调用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(); (); mShowing = false ; sendDismissMessage(); }

该方法后面的代码不用管它,先看 if(!mShowing){ … } 这段代码。

这个 mShowing 变量就是判断对话框是否已关闭的。

因此,我们在代码中通过设置这个变量就可以使系统认为对话框已经关闭,就不再继续关闭对话框了。

由于 mShowing 也是 private 变量,因此,也需要反射技术来设置这个变量。

我们可以在对话框按钮的单击事件中设置 mShowing ,代码如下:

try { Field field = dialog.getClass() .getSuperclass().getDeclaredField( " mShowing " ); essible( true ); // 将mShowing变量设为false,表示对话框已关闭 field.set(dialog, false ); dialog.dismiss();

} catch (Exception e) {

}

将上面的代码加到哪个按钮的单击事件代码中,哪个按钮就再也无法关闭对话框了。

如果要关闭对话框,只需再将 mShowing 设为 true 即可。

要注意的是,在一个按钮里设置了 mShowing 变量,也会影响另一个按钮的关闭对话框功能,因此,需要在每一个按钮的单击事件里都设置 mShowing 变量的值。

本文来自CSDN博客,转载请标明出处: /nokiaguy/archive/2010/07/27/5770263.aspx

请教个问题:AlertDialog创建个对话框,怎么动态控制单选或多选框选项的选中状态

写多了怕看着麻烦。

写个例子。

第一步:对话框里多选框的初始状态是只选中了第一个选项。

第二步.打开对话框,在多选框里选上了第二个选项,点击“取消”按钮,关闭对话框。

第三步:再次打开该对话框:按照正常思路来说,上次是点击“取消”按钮的,所以第二步的操作应该是无效的,多选框应该只有第一个选项被选中。

但实际情况第二个选项还是被选中的。

(安卓里默认记住上次的操作)我就是想解决这样的一个问题,点击了取消按钮时要取消掉该次做的修改。

所以需要动态的对多选框选项进行操作。

求指点。







如何使用 AlertDialog 的返回值

在大多数情况下,我需要用户进行选择,很多倍。

(我做的东西和提高消息框为用户作出的选择,继续做其他的事 (也许称为块))所以我写了一个常见的函数 public static void ShowMsgDialog(Context self,String title, String msg) 虽然它正确地响应用户的操作,但始终挂起 (的手段同时单击按钮前, 一个操作值都是可见的全局变量的值) 是存在着可能还在消息框中的任何函数返回值并使用它像这样: int ret = ShowMsgDialog(Context self,String title, String msg); 以下是我的代码: public class MainActivity extends Activity { private Button button1; enum Answer { YES, NO, ERROR}; static Answer choice; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button1 = (Button)findViewById(R.id.button1); button1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub ShowMsgDialog(MainActivity.this, "Information", "you choice? "); if(choice == Answer.YES) Toast.makeText(MainActivity.this, "YOU CHOICED YES", Toast.LENGTH_LONG).show(); else if (choice == Answer.NO) Toast.makeText(MainActivity.this, "YOU CHOICED NO", Toast.LENGTH_LONG).show(); else Toast.makeText(MainActivity.this, "ERROR OCUS", Toast.LENGTH_LONG).show(); //int ret = ShowMsgDialog(MainActivity.this, "Information", "you choice? "); } }); } public static void ShowMsgDialog(Context self,String title, String Msg){ AlertDialog.Builder dlgAlert = new AlertDialog.Builder(self); dlgAlert.setTitle(title); dlgAlert.setMessage(Msg); dlgAlert.setPositiveButton("OK",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { // call your code here choice = Answer.YES; } }); dlgAlert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub choice = Answer.NO; } }); dlgAlert.show(); } } 解决方法 1: 我不认为有任何方式要从这样的 alertDialog 中获取值 int ret = ShowMsgDialog(Context self,String title, String msg); 因为的时候您将显示对话框按钮的 onClick() 将会已经完成。

所以我建议使用另一种实现的方法。

因为要创建 alertDialog 的方法里面有您的活动它是创建一个函数在您的活动像下面一样容易: public void userChoosed(String choise){ if(choice == Answer.YES) //YOUR CODE FOR YES HERE Toast.makeText(MainActivity.this, "YOU CHOICED YES", Toast.LENGTH_LONG).show(); else if (choice == Answer.NO) //YOUR CODE FOR NO HERE Toast.makeText(MainActivity.this, "YOU CHOICED NO", Toast.LENGTH_LONG).show(); } 在 onClick() 中调用您的方法 喜欢这个: dlgAlert.setPositiveButton("OK",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { userChoosed(Answer.YES); } }); dlgAlert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { userChoosed(Answer.NO); } });

android studio 怎么创建自定义alertdialog

DialogFragment DialogFragment是在Android3.0的时候被引入的,从其名字可以很直观的看出它是一种基于Fragment的Dialog,可以用来创建对话框,它是用来替代Dialog的。

一个新事物的出现是为了解决旧事物存在的问题,那不建议使用的Dialog存在什么问题呢?下面简单的说下。

Dialog存在问题 在手机配置发生变化后(比如:旋屏后),变化之前显示的Dialog,变化之后不会显示,更别提Dialog状态的恢复了。

管理自定义的Dialog和系统原生的Dialog麻烦 DialogFragment怎么解决Dialog存在的问题 DialogFragment说到底还是一个Fragment,因此它继承了Fragment的所有特性。

同理FragmentManager会管理DialogFragment。

在手机配置发生变化的时候,FragmentManager可以负责现场的恢复工作。

调用DialogFragment的setArguments(bundle)方法进行数据的设置,可以保证DialogFragment的数据也能恢复。

DialogFragment里的onCreateView和onCreateDIalog 2个方法,onCreateView可以用来创建自定义Dialog,onCreateDIalog 可以用Dialog来创建系统原生Dialog。

可以在一个类中管理2种不同的dialog。

用DialogFragment替代Dialog 既然DialogFragment有这些好处,那对项目中的Dialog用DialogFragment来进行替代。

如何关闭一个AlertDialog

[mw_shl_code=java,true]ad.setNegativeButton(R.string.project_title,new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } });[/mw_shl_code]

android alertdialog怎样使用

AlertDialog使用起来相当方便,无论是作为内容提示, 还是作为选项对话框,几行代码就可以搞定。

也可尝试Dialog类,它也可以自定义View,方法为setContentView。

然后使用Dialog.findViewById便可以得到View里面的孩子。

它比AlertDialog麻烦的是需要自定义内容,因为它并没有像AlertDialog那样提供很多的定义对话框内容的方法。

HostYun(月18元),CN2直连香港大带宽VPS 50M带宽起

对于如今的云服务商的竞争着实很激烈,我们可以看到国内国外服务商的各种内卷,使得我们很多个人服务商压力还是比较大的。我们看到这几年的服务商变动还是比较大的,很多新服务商坚持不超过三个月,有的是多个品牌同步进行然后分别的跑路赚一波走人。对于我们用户来说,便宜的服务商固然可以试试,但是如果是不确定的,建议月付或者主力业务尽量的还是注意备份。HostYun 最近几个月还是比较活跃的,在前面也有多次介绍到商...

vpsdime7美元/月,美国达拉斯Windows VPS,2核4G/50GB SSD/2TB流量/Hyper-V虚拟化

vpsdime怎么样?vpsdime是2013年成立的国外VPS主机商,以大内存闻名业界,主营基于OpenVZ和KVM虚拟化的Linux套餐,大内存、10Gbps大带宽、大硬盘,有美国西雅图、达拉斯、新泽西、英国、荷兰机房可选。在上个月搞了一款达拉斯Linux系统VPS促销,详情查看:vpsdime夏日促销活动,美国达拉斯vps,2G内存/2核/20gSSD/1T流量,$20/年,此次推出一款Wi...

ReadyDedis:VPS全场5折,1G内存套餐月付2美元起,8个机房可选_服务器安装svn

ReadyDedis是一家2018年成立的国外VPS商家,由印度人开设,主要提供VPS和独立服务器租用等,可选数据中心包括美国洛杉矶、西雅图、亚特兰大、纽约、拉斯维加斯、杰克逊维尔、印度和德国等。目前,商家针对全部VPS主机提供新年5折优惠码,优惠后最低套餐1GB内存每月仅需2美元起,所有VPS均为1Gbps端口不限流量方式。下面列出几款主机配置信息。CPU:1core内存:1GB硬盘:25GB ...

alertdialog为你推荐
189邮箱怎么发短信请问189邮箱怎样登录、发邮件?windows7正版验证如何在微软网站验证Win7系统是否正版的方法圣诞节网页制作我想在接下来的圣诞、元旦设计一个网站的宣传页面,哪里有好的公司帮我呢?vs2005快捷键vs中的一个快捷键智能公共广播系统公共广播系统的品牌都有哪些??智能公共广播系统四川成都智能公共广播linux操作系统好吗linux系统好不好学??腾讯汽车论坛如何推广一个小城市的汽车论坛做视频的免费软件求有哪种视频制作软件是全免费的啊?xp仿win7桌面主题XP系统可以装window7主题吗
网游服务器租用 韩国俄罗斯 idc测评网 免费网站监控 win8升级win10正式版 lamp配置 免费个人空间申请 数字域名 免空 微信收钱 日本bb瘦 柚子舍官网 seednet 双11秒杀 100m独享 百度云1t 重庆双线服务器托管 raid10 贵阳电信 工信部icp备案查询 更多