【总结】Android开发中遇到的各种坑
2015-10-12 00:27
387 查看
前言
最近在弄一个小项目练练手,本来想着还是很简单的,结果一路碰壁,觉得一定要记下来,免得以后再被坑。(持续更新)StackOverflow果然是一个神奇的网站,很多坑都可以在上面找到解决方案,当然,前提是要看得懂English,其实主要是会看代码即可,呵呵。
AlertDialog
我想点击按钮不关闭对话框
情景:弹出一个对话框,用于输入密码,当点击按钮后,对密码进行校验,通过校验则关闭对话框,并继续后面的操作,当密码没通过校验时,只提示信息,不关闭对话框。
这是一个比较常用的情景(个人认为 - -),但是Google并没有提供相关的API来让开发者控制什么时候关闭对话框,而且API里面已经把这个写死了(Google这么设计肯定也有道理的,毕竟提示框的功能本来就是提示而已),不管点击的是哪个按钮(positive / neutral / negative),最终都会调用
dismiss()来关闭
AlertDialog。
这是
OnClickListener的定义:
private final View.OnClickListener mButtonHandler = new View.OnClickListener() { @Override public void onClick(View v) { final Message m; 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); } else { m = null; } if (m != null) { m.sendToTarget(); } // Post a message so we dismiss after the above handlers are executed mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialog) .sendToTarget(); } };
再看看这个Handler如何处理这个Message:
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(); // <<- 看这里 } }
由此可见(注释已经写得很清楚了),在点击按钮后,
AlertDialog肯定会被关闭的。
既然看清内幕了,那么解决方案是什么呢?
重写
Button的
OnClickListener:How to prevent a dialog from closing when a button is clicked
注意: getButton 必须在 create 或者 show 之后调用,否则抛出NullPointerException
反射。(这是一个几乎可以解决任何问题大招)
通过反射,有好几种方法可以解决
AlertDialog的关闭问题。其中比较最简单的一种方法,就是修改
Dialog类中的
mShowing字段的值(这个对话框根本没显示呀,不需要dismiss了)。
定义一个设置mShowing的方法:
public void canCloseDialog(DialogInterface dialog, boolean close) try { Field field = dialog.getClass().getSuperclass().getDeclaredField("mShowing"); field.setAccessible(true); field.set(dialog, close); } catch (Exception e) { e.printStackTrace(); }
然后这样使用就可以了:
new AlertDialog.Builder(this) .setTitle("输入密码") .setView(passwdEditText) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { canCloseDialog(dialogInterface, false); // false表示不关闭 } }) .setNeutralButton(android.R.string.cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { canCloseDialog(dialogInterface, true); // true表示会被关闭 } }) .show();
本节到此结束,关于反射的其他方案就不说了,反正很少用到。
相关文章推荐
- Javah Error android.app.Activity not found的问题
- Android之图片缓存管理
- android开发教程21篇(强烈推荐,几乎每一篇都是精华教程)
- 闹钟AlarmAndMusic 和支持播放音乐效果的
- Android学习(九)AudioTrack(2)
- Android自定义控件
- android绕过permission验证及fork进程权限提升
- Android-onInterceptTouchEvent()和onTouchEvent()
- 10大开源Android项目
- Android Studio 1.4 新特性介绍
- Android Studio相关资料链接
- Android Studio相关资料链接
- Android基础之Android动画
- Android 中通过切割图片创建人物行走动画
- Android反射机制详解
- Android群英传读书笔记---自定义控件(-)
- Android与js交互实例
- 使用AIDL完成一次简单的Android进程间通信
- Android中应用程序获得系统签名权限
- Android NDK开发环境搭建(链接)