概述
在我们开发过程中,有时需要监听手机软键盘状态,但是Android没有这样的API,所以需要我们自己处理。
实现方案
实现效果与原理
先上一张效果图
![](http://pubimage.360doc.com/wz/default.gif)
可以看到我们准确的监听到了软键盘的弹出与收起事件
首先我们应该思考,从键盘弹出与隐藏这个动作中我们可以获得什么有用的信息呢?我们的View
布局在此过程中有可能发生变化,如果我们可以监听到这个变化,而且判定是由于软键盘造成的就OK了。
具体代码
下面就是按照上面的思路写出的代码,具体分析在代码后面:
public class KeyboardStateObserver { private static final String TAG = KeyboardStateObserver.class.getSimpleName(); public static KeyboardStateObserver getKeyboardStateObserver(Activity activity) { return new KeyboardStateObserver(activity); } private View mChildOfContent; private int usableHeightPrevious; private OnKeyboardVisibilityListener listener; public void setKeyboardVisibilityListener(OnKeyboardVisibilityListener listener) { this.listener = listener; } private KeyboardStateObserver(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard / 4)) { if (listener != null) { listener.onKeyboardShow(); } } else { if (listener != null) { listener.onKeyboardHide(); } } usableHeightPrevious = usableHeightNow; Log.d(TAG,"usableHeightNow: " + usableHeightNow + " | usableHeightSansKeyboard:" + usableHeightSansKeyboard + " | heightDifference:" + heightDifference); } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); Log.d(TAG,"rec bottom>" + r.bottom + " | rec top>" + r.top); return (r.bottom - r.top);// 全屏模式下: return r.bottom } public interface OnKeyboardVisibilityListener { void onKeyboardShow(); void onKeyboardHide(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
上面的代码主要干了这几件事情:
1:我们获取到了设置到Activity
页面里面的View
布局mChildOfContent
,这个就是我们在Layout文件中定义的View
。
2:通过mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener
为其设置一个布局变化监听,只要布局有任何变化,都会触发这个监听。例如显示或隐藏某个view
,由于输入使某个editview
高度变化等。
3:计算布局变化的高度,如果变化的高度大于布局有效高度的1/4,我们认为这个布局变化是由软键盘造成的。
4:触发键盘显示与隐藏的监听。
如何使用
使用非常简单,获取实例,设置监听,在回调中处理逻辑即可。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); KeyboardStateObserver.getKeyboardStateObserver(this). setKeyboardVisibilityListener(new KeyboardStateObserver.OnKeyboardVisibilityListener() { @Override public void onKeyboardShow() { Toast.makeText(MainActivity.this,"键盘弹出",Toast.LENGTH_SHORT).show(); } @Override public void onKeyboardHide() { Toast.makeText(MainActivity.this,"键盘收回",Toast.LENGTH_SHORT).show(); } }); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
note:此方式必须在弹出键盘时候,使页面原有布局发生变动,所以如果不起作用的话可以试着在AndroidManifest.xml文件中设置android:windowSoftInputMode=”adjustResize|stateHidden“”
隐患
由于我们设置为布局变动大于有效高度1/4就认为是由软键盘引起的,当遇到键盘高度小于1/4,或者布局由于设计原因会有高度变化大于1/4时都会出问题,但是这些情况都是极其罕见的。