Android 软键盘相关初探索
最近又遇到软键盘的问题,心想:是时候好好总结一下了。。
直奔主题!
一、 Manifest中的属性android:windowSoftInputMode
AndroidManifest.xml中activity有一个属性android:windowSoftInputMode
活动的主窗口如何与包含屏幕上的软键盘窗口交互。这个属性的设置将会影响两件事情:
- 软键盘的状态——是否它是隐藏或显示——当活动(Activity)成为用户关注的焦点。(
state...
属性) - 活动的主窗口调整——是否减少活动主窗口大小以便腾出空间放软键盘或是否当活动窗口的部分被软键盘覆盖时它的内容的当前焦点是可见的。(
adjust...
属性)
在这设置的值(除"stateUnspecified"和"adjustUnspecified"以外)将覆盖在主题中设置的值
该属性必须为下面列表的其中一项或一个"stata..."加上一个"adjust..."的组合
-
stateUnspecified
:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置(默认值)合适的状态就是说,系统不确定一定要显示,那就不显示
经测试发现,该属性和不同的adjust...属性配合有不同的效果。如果是adjustUnspecified,则不弹出软键盘,而另外两个则会弹出(PS:如果是adjustUnspecified属性,并且设置了ScrollView,在有EditText时是会显示软键盘的。。。)
-
stateUnchanged
:当这个Activity出现时,软键盘将一直保持在上一个Activity里的状态,无论是隐藏还是显示 -
stateHidden
:当用户选择该Activity时,软键盘被隐藏。也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity -
stateAlwaysHidden
:当用户选择该Activity时,软键盘被隐藏。不论如何到达这个页面 -
stateVisible
:当用户选择该Activity时,软键盘可见。也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity -
stateAlwaysVisible
:当用户选择该Activity时,软键盘被隐藏。不论如何到达这个页面 -
adjustUnspecified
:它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间。(默认值,他会根据情况选择adjustResize和adjustPan中的一种)系统选择的条件是当前布局是否可以滚动,借此来选择当前是使用
adjustResize
还是adjustPan
-
adjustResize
:该Activity总是调整屏幕的大小以便留出软键盘的空间及压缩布局中间空白的地方来显示软键盘,但是如果内容过多,空白太小,不足以显示软键盘,那软键盘将会覆盖界面上的一些内容,导致不能看到输入的内容(若布局可以滚动,则不存在该问题)
若设置全屏模式,改属性会失效
-
adjustPan
:该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间,当前窗口的内容将自动移动(整体向上)以便当前焦点从不被键盘覆盖并且用户总是能看到输入的内容
因此:
如果不想在进入或返回Activity时,跳出软键盘,请使用stateAlwaysHidden
属性
若是想要在进入界面时显示软键盘,返回时不显示,则请使用stateVisible
属性(PS:就算没有EditText也会显示软键盘)
adjust...
属性,建议使用默认值(他会根据不同的情况,帮你适应),如果,想要压缩空间显示软键盘,请设置ScrollView,使得界面可以滚动,否则有可能出现键盘遮挡控件的情况
每个属性介绍较为详细了,可以根据各自的情况取用
参考:
查阅了网上一些资料,但有些网站内容雷同,如不知道谁copy谁的,也不知道谁是原创,暂时先不贴了。。。
二、 焦点相关
Touch Mode
对于android触屏手机来说 在整个系统的运行期间都是处于TouchMode模式(触摸模式)
Android关于焦点的方法
setFocusable()
:设置view是否有资格接收焦点
isFocusable()
:检查view是否具有接受焦点的资格
setFocusableInTouchMode()
:在触摸模式下,设置是否有资格接收焦点
isFocusableInTouchMode()
:在触摸模式下,view是否有具有焦点的资格
其中如果setFocusableInTouchMode为true,setFocusable也要为true,才会有用
requestFocus()
:请求获取焦点
该方法可以有参数,设置移动focus的方向
FOCUS_LEFT,
FOCUS_UP,
FOCUS_RIGHT,
FOCUS_DOWN
requestFocusFromTouch()
:触摸模式下请求焦点
viewGroup.requestChildFocus (View child, View focused)
- 父元素调用此方法
- child 将要获取焦点的子元素
- focused 现在拥有焦点的子元素
clearFocus()
:清除当前view的焦点
如果大家有遇到clearFocus无效的问题可以看看这篇文章,未知是否原创
isFocused()
:判断它自己是否拥有焦点
hasFocus()
:判断它自己或着自己的child是否拥有焦点
参考:
- http://www.cnblogs.com/frydsh/archive/2012/10/15/2724909.html
- http://gundumw100.iteye.com/blog/1779247
测试:
linearLayout.isFocusable() = false
linearLayout.isFocusableInTouchMode() = false
textView.isFocusable() = false
textView.isFocusableInTouchMode() = false
button.isFocusable() = true
button.isFocusableInTouchMode() = false
editText.isFocusable() = true
editText.isFocusableInTouchMode() = true
经简单测试,发现btn可以获取焦点,但是点击是没用的。而edit可以通过点击来获取焦点
上面也就挑了几个,大家有用到其他控件的可以自己测试一下
三、 软键盘的显示和隐藏
隐藏软键盘的方法
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0)
显示软键盘的方法
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(view,InputMethodManager.SHOW_FORCED);
如果输入法在窗口上已经显示,则隐藏,反之则显示
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
获取输入法打开的状态
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
boolean isOpen=imm.isActive();//isOpen若返回true,则表示输入法打开
PS:输入法打开的意思并不是说软键盘弹出,这个两个概念
参考:
四、 总结
目前,作者用到最多的情况是进入页面不显示软键盘,返回时,也不显示软键盘,有时,还要求点击空白处,隐藏软件盘,顺便伴随着EditText的焦点消失
因此使用用stateAlwaysHidden、adjustResize(需求为压缩空间,目前没有加ScrollView,但是我认为还是加上好,Android的适配是麻烦)、关于软键盘消失及取消EditText的焦点就涉及到Focus的几个方法了,setFocusable,setFocusableInTouchMode,requestFocus,clearFocus等
相信上面的一些解释可以解决很多问题,至于原理的探索,就待日后吧。