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那样提供很多的定义对话框内容的方法。

月神科技 国内上新成都高防 全场八折促销续费同价!

月神科技是由江西月神科技有限公司运营的一家自营云产品的IDC服务商,提供香港安畅、香港沙田、美国CERA、成都电信等机房资源,月神科技有自己的用户群和拥有创宇认证,并且也有电商企业将业务架设在月神科技的平台上。本次带来的是全场八折促销,续费同价。并且上新了国内成都高防服务器,单机100G集群1.2T真实防御,上层屏蔽UDP,可定制CC策略。非常适合网站用户。官方网站:https://www.ysi...

Hostiger发布哥伦布日提供VPS主机首月七折优惠 月费2.79美元

Hostiger商家我们可能以前也是有见过的,以前他们的域名是Hostigger,后来进行微调后包装成现在的。而且推出Columbus Day哥伦布日优惠活动,提供全场的VPS主机首月7折月付2.79美元起的优惠。这里我们普及一下基础知识,Columbus Day ,即为每年10月12日,是一些美洲国家的节日,纪念克里斯托弗·哥伦布在北美登陆,为美国的联邦假日。Hostiger 商家是一个成立于2...

ZJI:520元/月香港服务器-2*E5-2630L/32GB/480G SSD/30M带宽/2IP

ZJI发布了一款7月份特别促销独立服务器:香港邦联四型,提供65折优惠码,限量30台(每用户限购1台),优惠后每月520元起。ZJI是原来Wordpress圈知名主机商家:维翔主机,成立于2011年,2018年9月启用新域名ZJI,提供中国香港、台湾、日本、美国独立服务器(自营/数据中心直营)租用及VDS、虚拟主机空间、域名注册等业务。下面列出这款服务器的配置信息。香港邦联四型CPU:2*E5-2...

alertdialog为你推荐
goalgoalgoal哆啦小子和哆啦A梦是一个型号的吗?msn邮箱后缀MSN 可以添加哪些后缀的iphone12或支持北斗导航iphone12是问题机吗windows7系统要求Windows7系统对电脑配置的要求,dnf客户端消失最近DNF玩着玩着客户端忽然无故消失,怎么回事创业好项目论坛谁能提供点真实可靠的,网络创业赚钱项目?智能公共广播系统四川成都智能公共广播cf服务器爆满CF老是服务器爆满prepare的用法prepare和prepare for 用法有什么区别啊微软永久关闭实体店微软windows10易升怎么关闭
域名服务器的作用 快速域名备案 什么是域名解析 xen panel1 本网站服务器在美国 vip购优汇 php空间购买 安徽双线服务器 双12 空间购买 smtp服务器地址 阿里云邮箱登陆 域名转入 免费稳定空间 创速 广州服务器托管 密钥索引 globalsign vi命令 更多