前言:笔者目前在开发的一款软件属于工具类软件,主要用途是用于收集客户信息,因此涉及到很多EditText和软键盘交互的优化问题,今天产品提出默认软键盘显示优化的需求,明天提出进入某个页面EditText,不主动获取焦点,软键盘不主动弹窗的需求~~~岂是一个“烦”字,烦归烦,有需求,就得开发,为了以后少走弯路,笔者将这些优化一一记录下来,留着备用,也希望能帮到其他人 。
正文:笔者从以下四个方向讲解关于软键盘的优化问题
1:软键盘弹出的默认展示界面的问题;
Android 中限制软键盘输入的方法主要有两种:
1:使用 android:digits="0123",这种方法限制edittext只能输入指定字符(0,1,2,3),其他字符输入不了,并且不影响软件盘的默认展示。
2:使用 android:inputType="textEmailAddress",这种方法部分和num相关的值,会限制用户只能输入num类的字符,其他非num相关的值,不会限制用户任何输入,只会影响软件盘的默认展示。
android:inputType="phone" (@、字母、汉字不可输入;其他字符(数字键盘上的)都可以输入)),适用场景需要输入数字,手机号,金额,数量之类的输入框;
android:inputType="number"(只能输入数字,点(.)都无法输入),适用场景:卡号,手机号,不适合适用于输入金额以及数量等输入框;
android:inputType="numberDecimal"(只能输入数字和点(.)),最适合场景就是,输入金额,数量;
android:inputType="textEmailAddress"(默认英文和数字键盘,但是所有字符都可以输入)
android:inputType="textPassword"(默认英文和数字键盘,但是所有字符都可以输入)
android:inputType="textVisiblePassword" (默认英文和数字键盘,但是所有字符都可以输入)
备注:etPhone.setRawInputType();这个方法可以java代码中动态设置输入框软键盘默认显示,但是只影响软键盘展示,不限制输入内容;
2:软键盘弹出的时机;
如果不做任何处理,系统默认的是,进入页面,第一个输入框自动获取焦点软键盘自动弹出,这种用户交互方式,往往不是产品想要的,往往会提出以下优化需求:
需求1:edittext获取焦点,但是不弹出软键盘(白话:光标显示第一个输入框,不主动弹软键盘)
解决办法:
1.1:在第一个输入框的最直接父布局加入
android:focusable="true";android:focusableInTouchMode="true"
(效果:软键盘不弹出,光标不显示,其他输入框也不获取焦点,ps非直接父布局没有效果)
1.2: android:windowSoftInputMode="stateAlwaysHidden"
(效果:软键盘不弹出,光标显示在第一个输入框中)
需求2:edittext不获取焦点,当然软键盘不会主动弹出(光标也不显示);解决办法:
2.1:在第一个输入框的最直接父布局加入
android:focusable="true";android:focusableInTouchMode="true"
(效果:软键盘不弹出,光标不显示,其他输入框也不获取焦点,ps非直接父布局没有效果)
2.2:在父布局最顶部添加一个高度为0的EditText,抢了焦点但不展示;
3:软键盘遮挡界面的问题;
当界面中有输入框,需要弹起软键盘输入信息的时候,软键盘可能遮挡部分布局,更有甚者,当前输入框如果在屏幕下方,软键盘也会直接遮挡输入框,这种情况对用户体验是相当不友好的,所以要根据具体的情况作出相应的处理。
android定义了一个属性,名字为windowSoftInputMode, 这个属性用于设置Activity主窗口与软键盘的交互模式,用于避免软键盘遮挡内容的问题。我们可以在AndroidManifet.xml中对Activity进行设置。
stateUnspecified-未指定状态:软件默认采用的交互方式,系统会根据当前界面自动调整软键盘的显示模式。
stateUnchanged-不改变状态:当前界面软键盘状态由上个界面软键盘的状态决定;
stateHidden-隐藏状态:进入页面,无论是否有输入需求,软键盘是隐藏的,但是如果跳转到下一个页面软键盘是展示的,回到这个页面,软键盘可能也是展示的,这个属性区别下个属性。
stateAlwaysHidden-总是隐藏状态:当设置该状态时,软键盘总是被隐藏,和stateHidden不同的是,当我们跳转到下个界面,如果下个页面的软键盘是显示的,而我们再次回来的时候,软键盘就会隐藏起来。
stateVisible-可见状态:当设置为这个状态时,软键盘总是可见的,即使在界面上没有输入框的情况下也可以强制弹出来出来。
stateAlwaysVisible-总是显示状态:当设置为这个状态时,软键盘总是可见的,和stateVisible不同的是,当我们跳转到下个界面,如果下个页面软键盘是隐藏的,而我们再次回来的时候,软键盘就会显示出来。
adjustUnspecified-未指定模式:设置软键盘与软件的显示内容之间的显示关系。当你跟我们没有设置这个值的时候,这个选项也是默认的设置模式。在这中情况下,系统会根据界面选择不同的模式。
adjustResize-调整模式:当软键盘显示的时候,当前界面会自动重绘,会被压缩,软键盘消失之后,界面恢复正常(正常布局,非scrollView父布局);当父布局是scrollView的时候,软键盘弹出,会将布局顶起(保证输入框不被遮挡),不压缩,而且可以软键盘不消失的情况下,手动滑出被遮挡的布局;
adjustPan-默认模式:软键盘弹出,软键盘会遮挡屏幕下半部分布局,当输入框在屏幕下方布局,软键盘弹起,会自动将当前布局顶起,保证,软键盘不遮挡当前输入框(正常布局,非scrollView父布局)。当父布局是scrollView的时候,感觉没啥变化,还是自定将布局顶起,输入框不被遮挡,不可以手动滑出被遮挡的布局(白瞎了scrollView);
备注:
更多解决方法请参考大神:https://blog.csdn.net/smileiam/article/details/69055963(直接使用路径应该不构成侵权吧,第一次写公开博客,如有不当之处,请及时告知,谢谢);
4:软键盘及时退出的问题;
当用户输入完成之后,必须手动点击软键盘的收回键,软键盘才收起。如果能通过代码主动将软键盘收起,这对于用户体验来说,是一个极大的提升,思前想后,参考网上的文档,个人比较喜欢的实现方式是通过事件分发机制来解决这个问题,思路如下:
1:在baseActivity类中,重写dispatchTouchEvent;2:判断用户事件类型,如果是ACTION_DOWN的话,就判断当前点击位置,是否在之前的输入框范围内,如果在,不处理;不在,就隐藏软键盘;实现代码如下:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction()==MotionEvent.ACTION_DOWN){
if(isShouldHideInput(ev)){
hintKeyBord();
}
}
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
private boolean isShouldHideInput(MotionEvent ev) {
View view=getCurrentFocus();
if(view!=null&&viewinstanceof EditText){
int[]viewsArr=new int [2];
view.getLocationInWindow(viewsArr);
int left=viewsArr[0];
int top=viewsArr[1];
int buttom=top+view.getHeight();
int right=left+view.getWidth();
if(ev.getX()>=left&&ev.getX()<=right&&ev.getY()>top&&ev.getY()
//点击的是当前编辑框的区域
return false;
}else {
return true;
}
}
return false;
}
public void hintKeyBord(){
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm !=null) {
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}
}
备注:这种实现方式,并非个人原创,实现比较简单,有个唯一的缺点就是:当存在多个输入框的时候,切换输入框,弹窗也会消失后,重新弹起,这个不足到底是不是缺点,主要取决开发人员身边的产品,个人觉得可以接受。。。。。
gitHub大神写的这个可解决上面的不足:
https://github.com/yingLanNull/HideKeyboard(膜拜ing)
参考文章
完美解决点击空白处,隐藏软键盘;
关于EditText全面解析;
最后笔者最近开发过程中,遇到一个比较奇葩的需求,列表中手动输入数据,转变为android 语言就是:recycleView的item中包含edittext,当初看到这需求,心中数千羊驼飘过,但是羊驼飘过之后,还是按照这需求开发了,遇到的坑啊,下一期慢慢道来。。。
网友评论