Android中的弹出框在被点击时, 无论点击哪个按钮都会关闭窗口。 但是有的情况下我们不需要立即关闭窗口。下面的情况是弹出框中要求用户输入文件名, 并在点击确定时检查文件名的合法性, 不合法则提示用户重新输入, 弹出框要保持在界面上。 点击取消时弹出框消失。 这里通过对控件的反射来实现:
/**our button handler**/
private ButtonHandler bHandler;
//pop up dialog with own button handler
private void popUpDialog(AlertDialog dialog) {
/*
* alert dialog's default handler will always close dialog whenever user
* clicks on which button. we have to replace default handler with our
* own handler for blocking close action.
* Reflection helps a lot.
*/
try {
Field field = dialog.getClass().getDeclaredField("mAlert");
field.setAccessible(true);
//retrieve mAlert value
Object obj = field.get(dialog);
field = obj.getClass().getDeclaredField("mHandler");
field.setAccessible(true);
//replace mHandler with our own handler
field.set(obj, bHandler);
} catch (SecurityException e) {
Debug.error(e.getMessage());
} catch (NoSuchFieldException e) {
Debug.error(e.getMessage());
} catch (IllegalArgumentException e) {
Debug.error(e.getMessage());
} catch (IllegalAccessException e) {
Debug.error(e.getMessage());
}
//we can show this dialog now.
dialog.show();
}
/*
* define our own button handler, do not deal with dismiss message.
*/
class ButtonHandler extends Handler {
private WeakReference<DialogInterface> mDialog;
public ButtonHandler(DialogInterface dialog) {
mDialog = new WeakReference<DialogInterface>(dialog);
}
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 ;
}
}
}
然后创建一个AlertDialog时如下去调用:
//create dialog
mDialog = new AlertDialog.Builder(mContext)
.setView(selectImageView)
.setNegativeButton(android.R.string.cancel, mOnDialogClickListener)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int arg1) {
//check input file name
if (isValidFileName(fileNameInput.getText().toString())) {
String fileName = fileNameInput.getText().toString().trim();
mediaList.get(0).setName(fileName);
saveMedia(mediaList);
dialog.dismiss();
} else {
Toast.makeText(mContext, R.string.invalid_file_name, 1500).show();
}
}
}).create();
mOnDialogClickListener用来处理关闭窗口事件:
/*
* cancel dialog listener
*/
OnClickListener mOnDialogClickListener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int buttonId) {
switch (buttonId) {
case DialogInterface.BUTTON_NEGATIVE:
dialog.dismiss();
break;
case DialogInterface.BUTTON_POSITIVE:
break;
}
}
};
1 楼 ET焖猪仔 2011-03-29
学些了,楼主是怎么想到用反射的~ ?private WeakReference<DialogInterface> mDialog; 为什么这里用到弱引用? 期待解答~
2 楼 seya 2011-04-07
ET焖猪仔 写道
学些了,楼主是怎么想到用反射的~ ?private WeakReference<DialogInterface> mDialog; 为什么这里用到弱引用? 期待解答~
这种通过反射的方法也是从网上学来的, 不知原创是谁了。 弱引用的目的是方便垃圾回收, 这里的引用只是为了设置下Dialog里面的控件, 用完以后以后就不再需要持有这个句柄了。 使用弱引用就不会影响到原来对这个控件的垃圾回收过程。
3 楼 bluecountry 2011-08-12
膜拜了楼主的大作之后,果断选择自定义对话框...
就2个按钮 不用那么纠结
当然了 思路还是要学习一下
就2个按钮 不用那么纠结
当然了 思路还是要学习一下
4 楼 m331006 2011-08-16
楼主,为什么我对着写都不行的呢。。点击按钮时还是消失了。。。popUpDialog方法应该在哪里调用的??楼主看到了回我一下吧。。。急呢。谢谢了。