聊天界面,需要实现切换软键盘及输入框下面的其它聊天工具时,输入框的位置不变。Android系统未提供判断软键盘是否弹出及虚拟按键是否显示的方法(注:个人认为在inputManager.toggleSoftInput()方法的内部实现有可能有判断键盘是否弹出的方法,可惜无法点到源码,如果有谁找到了可通过反射调用的方法,请分享),在网上查到的资料,只能通过OnGlobalLayoutListener对可见屏幕高度的变化进行监听。但使用这个监听要注意,其监听的时机并非我们想象的只有屏幕可见高度变化才会调用,有时会调用多次;而且有些手机,即使隐藏了虚拟键,弹出键盘时也会自动弹出,所以在开发过程中遇到各种坑。尝试了大约5天,仍然无法完美解决,只能说还算可以接受。微信是直接锁定显示虚拟键,不允许用户隐藏,这个我在网上没查到资料,有哪位大神知道如何做到的,可以在下面评论。
无论如何也是自己花了这么长时间的成果,这期间耗费了不知多少脑细胞,所以还是把相关代码贴出来。
//获取虚拟按键高度
int id = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
final int vmKeyHeight = id == 0 ? 0 : getActivity().getResources().getDimensionPixelSize(id);
onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
decorView.getWindowVisibleDisplayFrame(rect);
if (isFirstShow) {//第一次,进行数据初始化
isFirstShow = false;
isVmKeyLastShow = rect.bottom != decorView.getHeight();
lastBottom = rect.bottom;
int initHight = EdoPreference.getInt(EdoPreference.KEY_KEYBOARD_HEIGHT, 0);
if (initHight > 0)
chatBottomView.setContentViewHeight(initHight);
else
chatBottomView.setContentViewHeight((int) (decorView.getHeight() * 0.4));
return;
}
int keyboardHeight = decorView.getHeight() - rect.bottom;//虚拟按键+键盘高度
Log.i(TAG, "onGlobalLayout: 键盘高度=" + keyboardHeight);
if (hasNavigationBar) {//手机有虚拟键
if (lastBottom == decorView.getHeight() - vmKeyHeight)
isVmKeyLastShow = true;
else if (lastBottom == decorView.getHeight())
isVmKeyLastShow = false;
int bottomHeight = EdoPreference.getInt(EdoPreference.KEY_KEYBOARD_HEIGHT, 0);
if (keyboardHeight > vmKeyHeight) {//键盘处于显示状态
if (lastBottom >= decorView.getHeight() - vmKeyHeight)
chatBottomView.isKeyboardOperatedByApp = false;//重置默认值
if (bottomHeight == keyboardHeight && !isVmKeyLastShow) {//虚拟键隐藏
Log.i(TAG, "onGlobalLayout: 虚拟键隐藏,高度不变");
lastBottom = rect.bottom;
return;
} else if (bottomHeight == keyboardHeight - vmKeyHeight && isVmKeyLastShow) {//虚拟按键显示
Log.i(TAG, "onGlobalLayout: 虚拟按键显示,高度不变");
lastBottom = rect.bottom;
return;
}
//其它情况,如切换输入法导致的键盘高度变化、横竖屏切换等
if (isVmKeyLastShow && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
keyboardHeight -= vmKeyHeight;
Log.i(TAG, "onGlobalLayout: 其它情况");
} else if (keyboardHeight == vmKeyHeight) {//虚拟按键显示,但有可能是键盘弹出/隐藏过程中显示的
if (!isVmKeyLastShow && lastBottom == decorView.getHeight()) {//之前未显示,现在显示了,应减小高度***(如果是先弹出虚拟键然后就弹出键盘会有问题)
Log.i(TAG, "onGlobalLayout: 虚拟按键处于显示状态");
keyboardHeight = bottomHeight - vmKeyHeight;
isVmKeyLastShow = true;
} else if (isVmKeyLastShow && lastBottom < decorView.getHeight() - vmKeyHeight) {//键盘隐藏,但虚拟按键显示
Log.i(TAG, "onGlobalLayout: 键盘隐藏,但虚拟按键显示");
if (chatBottomView.isKeyboardOperatedByApp) {//切换chatTool使app隐藏了键盘
chatBottomView.isKeyboardOperatedByApp = false;//重置默认值
Log.i(TAG, "onGlobalLayout: 切换chatTool使app隐藏了键盘");
} else {//user主动隐藏键盘
chatBottomView.changeChatToolsView(false);
Log.i(TAG, "onGlobalLayout: user主动隐藏键盘");
}
lastBottom = rect.bottom;
return;
} else
return;
} else if (keyboardHeight == 0) {//键盘和虚拟按键均隐藏
if (lastBottom < decorView.getHeight() - vmKeyHeight) {//键盘隐藏
Log.i(TAG, "onGlobalLayout: 键盘隐藏,虚拟按键隐藏");
if (chatBottomView.isKeyboardOperatedByApp) {//切换chatTool使app隐藏了键盘
chatBottomView.isKeyboardOperatedByApp = false;//重置默认值
Log.i(TAG, "onGlobalLayout: 切换chatTool使app隐藏了键盘");
} else {//user主动隐藏键盘
chatBottomView.changeChatToolsView(false);
Log.i(TAG, "onGlobalLayout: user主动隐藏键盘");
}
isVmKeyLastShow = false;
keyboardHeight = bottomHeight + vmKeyHeight;
// lastBottom = rect.bottom;
// return;
} else if (lastBottom == decorView.getHeight() - vmKeyHeight) {//虚拟按键隐藏
keyboardHeight = bottomHeight + vmKeyHeight;
Log.i(TAG, "onGlobalLayout: 虚拟按键隐藏了");
isVmKeyLastShow = false;
} else
return;
} else
return;
EdoLog.i(TAG, "onGlobalLayout: " + keyboardHeight);
lastBottom = rect.bottom;
if (keyboardHeight == bottomHeight)
return;
chatBottomView.setContentViewHeight(keyboardHeight);
chatBottomView.setVisibility(View.INVISIBLE);
chatBottomView.postDelayed(new Runnable() {//解决输入框闪烁问题
@Override
public void run() {
chatBottomView.setVisibility(View.VISIBLE);
chatBottomView.requestEdittextFocus();
}
}, 200);
EdoPreference.setPref(EdoPreference.KEY_KEYBOARD_HEIGHT, keyboardHeight);
} else {//手机没有虚拟按键
if (keyboardHeight > 0) {//键盘显示
int bottomHeight = EdoPreference.getInt(EdoPreference.KEY_KEYBOARD_HEIGHT, 0);
chatBottomView.isKeyboardOperatedByApp = false;
if (keyboardHeight == bottomHeight)
return;
chatBottomView.setContentViewHeight(keyboardHeight);
EdoPreference.setPref(EdoPreference.KEY_KEYBOARD_HEIGHT, keyboardHeight);
} else {//键盘隐藏
if (chatBottomView.isKeyboardOperatedByApp) {
chatBottomView.isKeyboardOperatedByApp = false;
} else {
chatBottomView.changeChatToolsView(false);
}
}
}
}
};
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);