前言:不知大家有没有这样的经历,在开发聊天页面时,就会想起微信那种切换菜单和键盘的交互是多么的顺滑,而自己所开发的页面在切换菜单和键盘时总是出现跳动问题。
先来看以下效果图:
目前我已经解决了切换键盘导致菜单上下跳动的问题。
实现原理:
1、利用设置布局为全屏时的特性(即SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)当设置这个后,布局不受软键盘的影响,但同时会引发另一个问题,当弹出软键盘之后输入框仍然在页面底部,此时输入框是被软键盘遮挡的。不过我们可以监听键盘弹出的高度从而我们自己把输入框顶起来,这一点有效的解决了切换菜单时跳动问题,那么我们接下来只需要处理好监测键盘弹出、收起以及它的高度就可以了
2、有了第一点作为前提,接下来就简单多了,我们把监测键盘弹出、收起以及它的高度做出来,就可以把这个功能做好了,废话不多说,上代码
public class SystemKeyboardUtils {
private View rootView;//activity的根视图
int rootViewVisibleHeight;//纪录根视图的显示高度
private OnKeyBoardListener onKeyBoardListener;
public SystemKeyboardUtils(Activity activity) {
//获取activity的根视图
rootView = activity.getWindow().getDecorView();
//监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
rootView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = () -> {
//获取当前根视图在屏幕上显示的大小
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
int visibleHeight = r.height();
if (rootViewVisibleHeight == 0) {
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变
if (rootViewVisibleHeight == visibleHeight) {
return;
}
//根视图显示高度变小超过200,可以看作软键盘显示了
if (rootViewVisibleHeight - visibleHeight > 200) {
if (onKeyBoardListener != null) {
onKeyBoardListener.onShow(rootViewVisibleHeight - visibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
//根视图显示高度变大超过200,可以看作软键盘隐藏了
if (visibleHeight - rootViewVisibleHeight > 200) {
if (onKeyBoardListener != null) {
onKeyBoardListener.onHide(visibleHeight - rootViewVisibleHeight);
}
rootViewVisibleHeight = visibleHeight;
return;
}
};
public void onDestroy(){
rootView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
public void setOnKeyBoardListener(OnKeyBoardListener onKeyBoardListener) {
this.onKeyBoardListener = onKeyBoardListener;
}
public interface OnKeyBoardListener {
void onShow(int height);
void onHide(int height);
}
public static void hideSoftInput(@NonNull final View view) {
InputMethodManager imm =
(InputMethodManager)view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) return;
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
public static void showSoftInput(Context context) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) {
return;
}
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
}
详细说明已经贴到代码里了
3、有了前两点作为支撑,我们就是要做好以下几点:
1>软键盘弹出时,我们把输入框那一栏顶起来
2>软键盘收起时,我们把输入框也收起来
3>在键盘弹出来的时候,切换菜单时我们只需要收起键盘以及让菜单显示出来即可
那么做好以上3点工作,这个聊天页面的交互就不会出现跳动问题了。
4、为了更好的适配更多的场景,我采用的设置方案是这样的---底部输入框和菜单栏呈上下结构,通过修改菜单栏的高度来达到顶起输入框和收起的目的,还有一点就是所有显示在菜单栏区域的都放在黑色区域,如下图所示:
当软键盘弹出时,上图中黑色菜单栏区域设置为和键盘相同的高度,这样输入框一栏就会保持在键盘上方,接下来切换菜单时,把键盘隐藏起来,并且让相应的菜单显示出来即可
结束语:
为了大家方便,我已经把代码放到了Github上,并且适配了绝大多数使用场景,欢迎star
传送门: