前言
在产品迭代的过程中,为了优化用户体验,展示我们产品的人文情怀,在有EditText控件或者自定义的输入框控件的页面,我们时常会被要求加入点击非输入框区域收起键盘的操作。下面我们来了解一下这个功能的实现。
正文
其实看到这个需求第一个想到的方法就是为其他控件setTouchListener,但是很显然这是个相当笨拙且会造成大量冗余代码的操作而且时间成本也相对较大,所以舍弃。这里我们最靠谱的做法还是基于Android的事件分发机制。对于事件分发机制不再赘述,感兴趣的请自行搜索。
前面说到产品迭代,其实无论是产品刚开始还是已经在迭代,代码的复用性都是我们应该考虑到的,以下代码均实现在基类BaseActivity中。
首先我们要重写dispatchTouchEvent()把操作放在用户点击的时候
/**
* 点击空白区域隐藏键盘.
*/
@Override
public boolean dispatchTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) { //把操作放在用户点击的时候
View v = getCurrentFocus(); //得到当前页面的焦点,ps:有输入框的页面焦点一般会被输入框占据
if (isShouldHideKeyboard(v, me)) { //判断用户点击的是否是输入框以外的区域
hideKeyboard(v.getWindowToken()); //收起键盘
}
}
return super.dispatchTouchEvent(ev);
}
重点来了,识别用户点击的区域
/**
* 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏
*
* @param v
* @param event
* @return
*/
private boolean isShouldHideKeyboard(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) { //判断得到的焦点控件是否包含EditText
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0], //得到输入框在屏幕中上下左右的位置
top = l[1],
bottom = top + v.getHeight(),
right = left + v.getWidth();
if (event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom) {
// 点击位置如果是EditText的区域,忽略它,不收起键盘。
return false;
} else {
return true;
}
}
// 如果焦点不是EditText则忽略
return false;
}
最后一步,收起键盘
/**
* 获取InputMethodManager,隐藏软键盘
* @param token
*/
private void hideKeyboard(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
OK,这样继承基类BaseActivity的左右有输出框并且使用系统默认键盘的页面就都实现了功能。
接下来我们看看自定义安全键盘如何来实现这个需求,自定义安全键盘的实现请看我写的这篇安卓开发 自定义软键盘 从原理到应用 可更改个别键颜色等。
很简单我们在识别用户点击区域的地方加一点小动作,获取自定义键盘的在屏幕中上下左右的区域
int[] y = {0, 0};
ll_jianpan.getLocationInWindow(y);
int left1 = y[0],
top1 = y[1],
bottom1 = top1 + ll_jianpan.getHeight(),
right1 = left1 + ll_jianpan.getWidth();
在判断区域的时候新加条件
if ((event.getX() > left && event.getX() < right
&& event.getY() > top && event.getY() < bottom)||(event.getX() > left1 && event.getX() < right1
&& event.getY() > top1 && event.getY() < bottom1)) {
// 点击位置如果是EditText的区域,忽略它,不收起键盘。
return false;
} else {
return true;
}
当然如果想让某个指定的view点击不使键盘消失也可以这样操作。
后记
明明是个程序猿却喜欢优美的文字,从今天开始,每篇最后分享句子吧。
当我吃东西时,就只管吃;当我走路时,就只管走。
因为我既不生活在过去,也不生活在未来,我只有现在,它才是我感兴趣的。
如果你能永远停留在现在,那你将是最幸福的人。
生活就是一个节日,是一场盛大的庆典。
因为生活永远是,也仅仅是我们现在经历的这一刻。
—保罗柯艾《牧羊少年奇幻之旅》