盒子
盒子
文章目录
  1. 前言
    1. 自定义方法
    2. 调用Android API
    3. 自定义外部类

android 软键盘显隐

前言

最近遇到软键盘的显隐判断问题,原来也遇过一次,所以这次针对这类问题的解决方法做下记录,也希望帮助后面碰到相同问题的你们。

根据自己的经验,这里有三种解决方法,其实原理都是一样的。我们都知道软件盘的弹出,视图的布局会发生改变,所以可以通过布局的改变来判断是否显示了软件盘。

自定义方法

个人觉得它的灵活性相对于别的更高。因为这只是在类中定义一个方法,来判断是否软键盘触发了。这样你可以运用到任何监听事件中来获取软件盘的状态。示例代码如下:

判断状态:

1
2
3
4
5
6
7
8
9
10
private boolean isKeyboardShown(View rootView) {
final int softKeyboardHeight = 100;
Rect r = new Rect();
// 获取根布局的可视区域r
rootView.getWindowVisibleDisplayFrame(r);
DisplayMetrics dm = rootView.getResources().getDisplayMetrics();
// 本来的实际底部距离 - 可视的底部距离
int heightDiff = rootView.getBottom() - r.bottom;
return heightDiff > softKeyboardHeight * dm.density;
}

例如在onTouch中判断:

1
2
3
4
5
6
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && isKeyboardShown(chatContent.getRootView()))
manager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
return false;
}

调用Android API

其实查阅API发现Android已经帮我们实现了布局改变的监听的类,我们可以使用addOnGlobalLayoutListener来监听整个布局的状态。这个监听器在我们的布局发生改变时会调用onGlobalLayout方法,所以我们可以在其中进行操作。当然在使用该监听时要先获取整个视图树的观察者。

1
2
final View root = findViewById(R.id.main);
ViewTreeObserver observer = root.getViewTreeObserver();

再添加监听:

1
2
3
4
5
6
7
8
9
10
11
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = root.getRootView().getHeight() - root.getHeight();
if (heightDiff > 100){ //一般超过100视为弹出
//显示操作
}else{
//隐藏操作
}
}
});

自定义外部类

其实使用该方法就是自定义一个布局继承Android基本布局控件,然后在其中重写onMeasure方法,在该方法中的操作与前面的基本类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = MeasureSpec.getSize(heightMeasureSpec);
Activity activity = (Activity) getContext();
Rect rect = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int screenHeight = activity.getWindowManager().getDefaultDisplay().getHeight();
int diff = (screenHeight - statusBarHeight) - height;
if (listener != null) {
listener.onSoftKeyboardShown(diff > 100);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

这里自定义与实现了监听接口

1
2
3
4
5
6
7
8
9
public interface Listener {
void onSoftKeyboardShown(boolean isShowing);
}
private Listener listener;
public void setListener(Listener listener) {
this.listener = listener;
}

最后在xml中使用该自定义布局,目标类中绑定调用:

1
2
RelativeLayoutThatDetectsSoftKeyboard chatLayout = (RelativeLayoutThatDetectsSoftKeyboard) findViewById(R.id.chat_bottm);
chatLayout.setListener(this);
1
2
3
4
5
@Override
public void onSoftKeyboardShown(boolean isShowing) {
if (isShowing)
//显示操作
}

这个的好处就是逻辑对外封装、解耦了,只要根据isShowing的值进行操作。

好了,我只是大自然的搬运工,到底要用哪种就自己视情况而定吧

转载请指明出处 idisfkj博客:https://idisfkj.github.io

支持一下
赞赏是一门艺术