前言
最近遇到软键盘的显隐判断问题,原来也遇过一次,所以这次针对这类问题的解决方法做下记录,也希望帮助后面碰到相同问题的你们。
根据自己的经验,这里有三种解决方法,其实原理都是一样的。我们都知道软件盘的弹出,视图的布局会发生改变,所以可以通过布局的改变来判断是否显示了软件盘。
自定义方法
个人觉得它的灵活性相对于别的更高。因为这只是在类中定义一个方法,来判断是否软键盘触发了。这样你可以运用到任何监听事件中来获取软件盘的状态。示例代码如下:
判断状态:
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