有時候在開發(fā)過程中需要監(jiān)聽軟鍵盤的顯示狀態(tài),在顯示和隱藏鍵盤時對UI做出相應(yīng)的調(diào)整。Android官方?jīng)]有提供獲取軟鍵盤高度和狀態(tài)的方法,但是可以通過監(jiān)聽當(dāng)前應(yīng)用的高度變化計算
出軟鍵盤的高度。
首先獲取到activity布局的最外層layout,通過調(diào)用getWindowVisibleDisplayFrame獲取到整個應(yīng)用可以顯示的區(qū)域,這其中包括ActionBar和狀態(tài)欄,但不含設(shè)備底部的虛擬按鍵。
再通過調(diào)用getRootView().getHeight(),獲取整個屏幕的高度。同樣,這個高度也不含虛擬按鍵的高度。
通過比較這兩個高度,可以推斷出軟鍵盤是否顯示,并且獲取到軟鍵盤的高度。
需要注意的是,這種方法前提是軟鍵盤會影響界面布局,所以需要在AndroidManifest里給activity添加android:windowSoftInputMode="adjustResize"。
具體實(shí)現(xiàn)代碼如下:
private LinearLayout layout_main;
private TextView text;
// 狀態(tài)欄的高度
private int statusBarHeight;
// 軟鍵盤的高度
private int keyboardHeight;
// 軟鍵盤的顯示狀態(tài)
private boolean isShowKeyboard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusBarHeight = getStatusBarHeight(getApplicationContext());
text = (TextView) findViewById(R.id.text);
layout_main = (LinearLayout) findViewById(R.id.layout_main);
layout_main.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
}
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 應(yīng)用可以顯示的區(qū)域。此處包括應(yīng)用占用的區(qū)域,
// 以及ActionBar和狀態(tài)欄,但不含設(shè)備底部的虛擬按鍵。
Rect r = new Rect();
layout_main.getWindowVisibleDisplayFrame(r);
// 屏幕高度。這個高度不含虛擬按鍵的高度
int screenHeight = layout_main.getRootView().getHeight();
int heightDiff = screenHeight - (r.bottom - r.top);
// 在不顯示軟鍵盤時,heightDiff等于狀態(tài)欄的高度
// 在顯示軟鍵盤時,heightDiff會變大,等于軟鍵盤加狀態(tài)欄的高度。
// 所以heightDiff大于狀態(tài)欄高度時表示軟鍵盤出現(xiàn)了,
// 這時可算出軟鍵盤的高度,即heightDiff減去狀態(tài)欄的高度
if(keyboardHeight == 0 && heightDiff > statusBarHeight){
keyboardHeight = heightDiff - statusBarHeight;
}
if (isShowKeyboard) {
// 如果軟鍵盤是彈出的狀態(tài),并且heightDiff小于等于狀態(tài)欄高度,
// 說明這時軟鍵盤已經(jīng)收起
if (heightDiff <= statusBarHeight) {
isShowKeyboard = false;
onHideKeyboard();
}
} else {
// 如果軟鍵盤是收起的狀態(tài),并且heightDiff大于狀態(tài)欄高度,
// 說明這時軟鍵盤已經(jīng)彈出
if (heightDiff > statusBarHeight) {
isShowKeyboard = true;
onShowKeyboard();
}
}
}
};
private void onShowKeyboard() {
// 在這里處理軟鍵盤彈出的回調(diào)
text.setText("onShowKeyboard : keyboardHeight = " + keyboardHeight);
}
private void onHideKeyboard() {
// 在這里處理軟鍵盤收回的回調(diào)
text.setText("onHideKeyboard");
}
@Override
protected void onDestroy() {
super.onDestroy();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
layout_main.getViewTreeObserver().removeGlobalOnLayoutListener(globalLayoutListener);
} else {
layout_main.getViewTreeObserver().removeOnGlobalLayoutListener(globalLayoutListener);
}
}
// 獲取狀態(tài)欄高度
public static int getStatusBarHeight(Context context) {
try {
Class<?> c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
int x = Integer.parseInt(field.get(obj).toString());
return context.getResources().getDimensionPixelSize(x);
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}