我们常常需要知道软键盘的隐藏显示状态来对布局做一些操作,然后Android原生并没有提供一个接口或者监听让我们能够方便获得软键盘的状态。因此,我们只能别图它径来间接获取。

正常情况下,屏幕高度 = 屏幕可见高度+状态栏高度,当软键盘弹出时屏幕高度 = 屏幕可见高度+状态栏高度+软键盘高度。我们可通过获取屏幕高度,再获取屏幕可见高度、状态栏高度,再做一个减法即可获取软键盘高度。

在上代码之前,先说说能够帮我们实时监听软键盘高度变化的类ViewTreeObserver。

ViewTreeObserver类,它是一个View视图树的观察者类。 当一个View attach到一个窗口上时就会创建一个ViewTreeObserver对象,这样当一个View的视图树发生改变时,

就会调用该对象的某个方法,将事件通知给每个注册的监听者。 OnGlobalLayoutListener是ViewTreeObserver中定义的众多接口中的一个, 它用来监听一个视图树中全局布局的改变或者视图树中的某个视图的可视状态的改变。
当软键盘由隐藏变为显示,或由显示变为隐藏时,都会调用当前布局中所有存在的View中的  ViewTreeObserver对象的dispatchOnGlobalLayout()方法,此方法中会遍历所有已注

册的OnGlobalLayoutListener,执行相应的回调方法,将全局布局改变的消息通知给每个注册的监听者。 
获取屏幕高度:

WindowManager wm = this.getWindowManager();
int screenHeight = wm.getDefaultDisplay().getHeight();

获取状态栏高度:

int stateHeight = this.getStatusHeight(this);
public static int getStatusHeight(Context context) {

int statusHeight = -1;
try {

Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
int height = Integer.parseInt(clazz.getField("status_bar_height")
.get(object).toString());
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}接下来,借助OnGlobalLayoutListener监听软键盘状态,顺便获取软键盘高度。
boolean isKeyboardShowing;
private OnGlobalLayoutListener mLayoutChangeListener;
//注册布局变化监听   
getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(mLayoutChangeListener);//通常情况下,对editText做操作的时候才需要监听软件盘,因此也可在EditText上注册监听
edt.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutChangeListener);

mLayoutChangeListener = new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//判断窗口可见区域大小
Rect r = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
//如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。
//屏幕高度减去可见高度+状态栏高度,才是真正的软键盘高度  高度单位为px
int heightDifference = screenHeight - (r.bottom - r.top+stateHeight);
Log.e("MainActivity", "screenHeight:"+screenHeight+"   r.bottom: "
+r.bottom+"    r.top:"+r.top+"    stateHeight:"+stateHeight);
//得到软键盘的隐藏和显示状态  返回值为true即软键盘为显示状态,否则为隐藏状态
isKeyboardShowing = heightDifference > screenHeight/3;

}
};最后,移除布局变化监听  不然可能会导致内存泄露。
protected void onDestroy() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutChangeListener);
} else {
getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(mLayoutChangeListener);
}
super.onDestroy();
};