前言
在android开发中经常使用InputMethodManager来操作软键盘的显示隐藏,我们可以通过此类来控制显示/隐藏软键盘。
使用场景
在具有EditText的界面中,一般进入界面后,EditText控件会自动获取焦点,并弹出输入框,另外,当点击其它按键或者后台返回数据时(如密码验证失败),也可触发EditText使其弹出软键盘。
显示/隐藏 软键盘函数
弹出输入框的方式有多种,但是大部分方式会有一些弊端,如单一的使用edittext.requestFocus( )函数,有可能在获取焦点后,焦点又转移到其他控件,此时不能保证软键盘弹出。
在读NumberPicker源码时,我发现了如下两个方法:
/**
* Shows the soft input for its input text.
*/
private void showSoftInput() {
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
if (inputMethodManager != null) {
if (mHasSelectorWheel) {
mInputText.setVisibility(View.VISIBLE);
}
mInputText.requestFocus();
inputMethodManager.showSoftInput(mInputText, 0);
}
}
/**
* Hides the soft input if it is active for the input text.
*/
private void hideSoftInput() {
InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
if (inputMethodManager != null && inputMethodManager.isActive(mInputText)) {
inputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0);
if (mHasSelectorWheel) {
mInputText.setVisibility(View.INVISIBLE);
}
}
}
这两个方法分别用来显示和隐藏软键盘输入法。但是由于InputMethodManager中的方法peekInstance( )是隐藏的:
/**
* Private optimization: retrieve the global InputMethodManager instance,
* if it exists.
* @hide
*/
public static InputMethodManager peekInstance() {
return sInstance;
}
因此如果在项目中使用这两个方法时,一般可采用反射的方式:
/**
* Shows the soft input for its input text, by reflection mechanism
*/
public void showSoftKeyboard() {
Object o = null;
try{
Class<?> threadClazz = Class.forName("android.view.inputmethod.InputMethodManager");
Method method = threadClazz.getDeclaredMethod("peekInstance" );//return sInstance
Method[] methods = threadClazz.getDeclaredMethods();
method.setAccessible( true);
o = method.invoke( null);
if(o == null ){
return;
}
InputMethodManager inputMethodManager = (InputMethodManager)o;
if (inputMethodManager != null) {
edittext.requestFocus();
inputMethodManager.showSoftInput( edittext, 0);
}
} catch (Exception e){
}
}
/**
* Hides the soft input if it is active for the input text, by reflection mechanism
*/
public void hideSoftKeyboard(){
Object o = null;
try{
Class<?> threadClazz = Class.forName("android.view.inputmethod.InputMethodManager");
Method method = threadClazz.getDeclaredMethod("peekInstance");//return sInstance
Method[] methods = threadClazz.getDeclaredMethods();
method.setAccessible( true);
o = method.invoke( null);
if(o == null ){
return;
}
InputMethodManager inputMethodManager = (InputMethodManager)o;
if (inputMethodManager != null && inputMethodManager.isActive(edittext )) {
inputMethodManager.hideSoftInputFromWindow(edittext .getWindowToken(), 0);
}
} catch (Exception e){
}
}
以上两个方法经测试后有效。
场景:
界面设置不自动弹出软键盘,手动/后台触发
为了不使界面自动弹出软键盘,比较常用的方式由两种:
1.第一种方法:采用在manifest文件中的某个Activity声明处加上如下属性:
android:windowSoftInputMode="adjustUnspecified|stateHidden"
这种方式直接指明此activity界面的软键盘初始状态是隐藏的。
2.第二种方法:在布局文件中,为顶层的ViewGroup添加如下属性:
android:focusable= "true"
android:focusableInTouchMode= "true"
这两行代码将焦点置于布局文件的最外层ViewGroup上,EditText不会获取焦点,因此在进入界面时,软键盘不会自动弹出。
注意,这两种方式下,要想再次弹出软键盘,采用的方法略有不同。
在第一种情况下(即,设置Activity属性),总结如下:
1.无论是否是在onCreate()中使用如下代码,均无法弹出软键盘。
edittext.setFocusable(true);
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();
2.如果在onCreate()中使用如下代码,仍然无法弹出软键盘。
edittext.setFocusable(true);
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();
showSoftInput();
3.在onCreate()中可以使用此方法,弹出软键盘。
edittext.setFocusable(true);
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();
edittext.postDelayed(new Runnable() {
@Override
public void run() {
showSoftKeyboard();
}
}
在第二种情况下(即,设置Layout文件中父控件获取焦点),总结如下:
1.如果想在onCreate()中弹出软键盘,只需要使用如下代码:
edittext.setFocusable(true);
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();
2.如果是在点击其它控件后想要触发EditText弹出软键盘,那么需要添加主动显示软键盘的代码:
edittext.setFocusable(true);
edittext.setFocusableInTouchMode(true);
edittext.requestFocus();
showSoftKeyboard();
需要添加showSoftKeyboard( )的原因是:当点击了其它按键后,焦点又回到了其它控件,因此需要强制添加showSoftKeyboard( )函数。