经常会遇到需要控制输入法的情况,如输入法显示、隐藏; 输入法弹出后,界面被顶上去或编辑框被遮挡等问题;下面分为几个部分总结输入法属性设置,及输入法控制。
一、windowSoftInputMode设置
activity主窗口与软键盘的交互模式,可以用来避免输入法面板遮挡问题
这个属性能影响两件事情:
a. 当有焦点产生时,软键盘是隐藏还是显示
b. 是否减少活动主窗口大小以便腾出空间放软键盘
【1】 在manifest设置
软键盘显示或隐藏的属性有以下几个选择:
【A】stateUnspecified:软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置
【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示
【C】stateHidden:当用户选择该Activity时,软键盘被隐藏——也就是,当用户导航到该Activity时,而不是由于离开另一个Activity返回到它。
【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘总是被隐藏的;无论是导航到该activity,或是从其他Activity返回到该Activity
stateHidden 与stateAlwaysHidden的区别: 后者,无论何种情况到达该Activity都隐藏输入法,而前者,只确保首次进入该Activity时隐藏输入法;
【E】stateVisible:软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)
【F】stateAlwaysVisible:当用户选择这个Activity时,软键盘是可见的-- 无论是导航到它,或是由于离开另一个Activity返回到它
这两者的区别于 hidden和alwaysHiden一样;
示例:
HomeFragmentActivity的设置:
android:windowSoftInputMode
=
"stateAlwaysHidden|adjustPan" 无论何时到达该界面该界面都隐藏输入法
FindFriendActivity的设置:
android:windowSoftInputMode
=
"stateVisible|adjustPan", 首次进入该界面时,显示输入法; 如果改为
stateAlwaysVisible,那么从其他界面返回该界面时,输入法也会自动弹出
当前窗口变化模式有以下几个选择:
【G】adjustUnspecified:它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。
【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间;即当前窗口的size 会发生变化;
【I】adjustPan:该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分,如果输入法弹出时,焦点不被覆盖,那么窗口不会自动移动。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
【2】代码设置
windowSoftInputMode也可以在代码中设置,效果一样
二、控制输入法隐藏、显示 状态
除了进入Activity时,控制输入法的显示/隐藏状态,在Activity使用过程中,有时也需要手动控制。
【1】 切换输入法的显示/隐藏状态 :
如果输入法在窗口上已经显示,则隐藏,反之则显示
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.
INPUT_METHOD_SERVICE
);
imm.toggleSoftInput(0, InputMethodManager.
HIDE_NOT_ALWAYS
);
该方法优点:无需知道当前窗口是否有焦点,也就无需找到该窗口中能获取焦点的控件了;
该方法缺点:如果事先不确定输入法是显示还是隐藏的状态,那么该方法可能无法达到预期效果; 只有确定当前输入法的状态才能使用该方法;
【2】强制弹出输入法
imm.showSoftInput(
currentfocusedView
, 0);
【3】强制隐藏输入法
imm.hideSoftInputFromWindow(
currentfocusedView
.getWindowToken(),
0
)
方法【2】、【3】 必须找到当前具有焦点的控件。 如果当前Activity失去焦点
如弹出对话框,则该Activity无法控制输入法状态了,即上面的方法不起任何效果
第一个参数
currentfocusedView是当前窗口具有焦点的控件,一般是EditText;
三、监控输入法是否弹出
android没有现成的方法告知上层,输入法的状态是显示的还是隐藏的, 但有时需要根据输入法的状态进行一些操作,如 “弹幕”界面,当输入法弹出时,隐藏弹幕面板,反之显示;
windowSoftInputMod
e属性中,
adjustResize模式,在输入法弹出时,会调整界面大小,可以通过界面大小变化来判断输入法是否弹出
【1】自定义界面布局根View
onSizeChanged
中监听大小变化,高度变小,说明输入法弹出,反之,输入法隐藏;
public
class
CheckSoftInputLayout
extends
FrameLayout{
private
OnResizeListener
onResizeListener
;
public
interface
OnResizeListener{
void
OnResize(
int
w,
int
h,
int
oldw,
int
oldh);
}
public
CheckSoftInputLayout(Context context, AttributeSet attrs) {
this
(context, attrs, 0);
}
public
CheckSoftInputLayout(Context context, AttributeSet attrs,
int
defStyle) {
super
(context, attrs, defStyle);
}
public
void
setOnResizeListener(OnResizeListener _listener) {
this
.
onResizeListener
= _listener;
}
@Override
protected
void
onSizeChanged(
int
w,
int
h,
int
oldw,
int
oldh) {
super
.onSizeChanged(w, h, oldw, oldh);
if
(
onResizeListener
!=
null
) {
onResizeListener
.OnResize(w, h, oldw, oldh);
}
}
}
【2】在listener事件中处理
Activity代码:
rootView
.setOnResizeListener(
new
OnResizeListener() {
@Override
public
void
OnResize(
int
w,
int
h,
int
oldw,
int
oldh) {
if
(h < oldh) {
//输入法弹出
//todo
}
else
{
//输入法关闭
//todo
}
}
});
注意:在manifest.xml中,activity的
windowSoftInputMode必须设置为
adjustResize