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

HostKvm新上联通CUVIP线路VPS,八折优惠后1G内存套餐$5.2/月起

最近上洛杉矶机房联通CUVIP线路主机的商家越来越多了,HostKvm也发来了新节点上线的邮件,适用全场8折优惠码,基于KVM架构,优惠后最低月付5.2美元起。HostKvm是一家成立于2013年的国人主机商,提供基于KVM架构的VPS主机,可选数据中心包括日本、新加坡、韩国、美国、中国香港等多个地区机房,君选择国内直连或优化线路,延迟较低,适合建站或者远程办公等。以洛杉矶CUVIP线路主机为例,...

捷锐数据399/年、60元/季 ,香港CN2云服务器 4H4G10M

捷锐数据官网商家介绍捷锐数据怎么样?捷锐数据好不好?捷锐数据是成立于2018年一家国人IDC商家,早期其主营虚拟主机CDN,现在主要有香港云服、国内物理机、腾讯轻量云代理、阿里轻量云代理,自营香港为CN2+BGP线路,采用KVM虚拟化而且单IP提供10G流量清洗并且免费配备天机盾可达到屏蔽UDP以及无视CC效果。这次捷锐数据给大家带来的活动是香港云促销,总共放量40台点击进入捷锐数据官网优惠活动内...

随风云-内蒙古三线BGP 2-2 5M 25/月 ,香港CN2 25/月 ,美国CERA 25/月 所有云服务器均支持5天无理由退款

公司成立于2021年,专注为用户提供低价高性能云计算产品,致力于云计算应用的易用性开发,面向全球客户提供基于云计算的IT解决方案与客户服务,拥有丰富的国内BGP、三线高防、香港等优质的IDC资源。公司一直秉承”以人为本、客户为尊、永续创新”的价值观,坚持”以微笑收获友善, 以尊重收获理解,以责任收获支持,以谦卑收获成长”的行为观向客户提供全面优质的互...

alertdialog为你推荐
外媒称华为加速南泥湾项目华为Nova系列有哪些潜在进入者?谷歌德语在线翻译德语翻译 不找你不代表我不想你 别用翻译器 谢谢~多重阴影[讨论]《多重阴影》的中文配音好熟悉啊!windowsphone手机Windows phone手机的优点和缺点微信语音在哪个文件夹电脑版微信的语音文件夹在哪个文件夹flv转换aviflv怎么转换成avilinux操作系统好吗linux系统好不好学??云图好看吗云图好看么?cad图批量打印如何批量打印CAD图纸?kakaotalk是什么我用kakaotalk跟韩国朋友聊天,但是韩文看不懂,求大侠帮助!!!
济南域名注册 59.99美元 阿里云代金券 css样式大全 mysql主机 bgp双线 183是联通还是移动 nerds 南通服务器 in域名 创建邮箱 免费外链相册 linode支付宝 ebay注册 防cc攻击 国外免费云空间 谷歌搜索打不开 新疆服务器 第八届中美互联网论坛 globalsign 更多