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

Virmach:1核/512M1核M1核512M/夏季美国vps促销,年付$7.2,9月更换AMD平台

virmach怎么样?virmach家这几年非常火,从商家的黑五闪购开始,以超低的价格吸引了大批的国人客户,而且商家的机器还是非常稳定的,站长手里的4.75刀年付已经用了两年了,非常稳定,不过商家到国内的线路一般,目前商家新上了夏季优惠促销,价格低到发指,年付7.2美元起,商家反馈将在9月开始更换AMD+NVMe平台,这个消息从年初就有了,不过一直没有更换,目前这个时间也不确定是否准确。点击进入:...

腾讯云轻量服务器老用户续费优惠和老用户复购活动

继阿里云服务商推出轻量服务器后,腾讯云这两年对于轻量服务器的推广力度还是比较大的。实际上对于我们大部分网友用户来说,轻量服务器对于我们网站和一般的业务来说是绝对够用的。反而有些时候轻量服务器的带宽比CVM云服务器够大,配置也够好,更有是价格也便宜,所以对于初期的网站业务来说轻量服务器是够用的。这几天UCLOUD优刻得香港服务器稳定性不佳,于是有网友也在考虑搬迁到腾讯云服务器商家,对于轻量服务器官方...

美国G口/香港CTG/美国T级超防云/湖北高防云服务器物理机促销活动 六一云

六一云 成立于2018年,归属于西安六一网络科技有限公司,是一家国内正规持有IDC ISP CDN IRCS电信经营许可证书的老牌商家。大陆持证公司受大陆各部门监管不好用支持退款退现,再也不怕被割韭菜了!主要业务有:国内高防云,美国高防云,美国cera大带宽,香港CTG,香港沙田CN2,海外站群服务,物理机,宿母鸡等,另外也诚招代理欢迎咨询。官网www.61cloud.net最新直销劲爆...

alertdialog为你推荐
怎样恢复系统如何恢复系统?iphone12或支持北斗导航苹果12几个版本magento模板magento1.9主题开发用哪个模板为基础好?呼叫中心搭建呼叫中心有几种建设方式啊?那种最省钱?dnf客户端消失地下城勇士登录 客户端消失微信语音在哪个文件夹电脑版微信的语音文件夹在哪个文件夹cf服务器爆满CF老是服务器爆满慕课网址如何加入慕课学习课程?发送验证码关联手机号码发送短信验证码发送验证码微信登录需要好友发验证码怎么办
私服服务器租用 如何注册网站域名 三级域名网站 泛域名解析 80vps burstnet 163网 长沙服务器 个人空间申请 ca4249 有奖调查 网站cdn加速 服务器干什么用的 免费申请网站 息壤代理 免费dns解析 卡巴斯基免费试用版 免费私人服务器 跟踪路由命令 web服务器是什么 更多