在做一些人性化的交互設計的時候,能夠獲取Android 鍵盤的顯示與隱藏狀態對我們有很大的幫助,但是Android 官方文檔中并沒有明確的給出 ,鍵盤顯示與隱藏的監聽,但是我們還是可以通過計算當前應用的高度變化來獲取鍵盤的狀態。手機QQ對于鍵盤的處理就非常好,有著以下的幾點人性化設計:
QQ效果圖
- 滑動時隱藏鍵盤
- 點擊除鍵盤區域隱藏鍵盤
- 當滾動到底部時繼續拉動彈出鍵盤
** 本文將一步一步講解實現上述三種設計 **
1.首先獲取鍵盤顯示隱藏狀態
獲取鍵盤顯示狀態的原理是:首先利用getRootView().getHeight() 獲取屏幕高度,在利用getWindowVisibleDisplayFrame 獲取應用顯示區域,但是這個區域不包含虛擬按鍵的區域(虛擬鍵盤、手機底部虛擬按鍵),我們根據前者與后者之差與狀態欄高度的比較來判斷鍵盤的顯示與隱藏狀態。
// 軟鍵盤的顯示狀態
private boolean ShowKeyboard;
private ViewTreeObserver.OnGlobalLayoutListener globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
// 應用可以顯示的區域。此處包括應用占用的區域,包括標題欄不包括狀態欄
Rect r = new Rect();
layoutMain.getWindowVisibleDisplayFrame(r);
// 鍵盤最小高度
int minKeyboardHeight = 150;
// 獲取狀態欄高度
int statusBarHeight = getStatusBarHeight(mContext);
// 屏幕高度,不含虛擬按鍵的高度
int screenHeight = layoutMain.getRootView().getHeight();
// 在不顯示軟鍵盤時,height等于狀態欄的高度
int height = screenHeight - (r.bottom - r.top);
if (ShowKeyboard) {
// 如果軟鍵盤是彈出的狀態,并且height小于等于狀態欄高度,
// 說明這時軟鍵盤已經收起
if (height - statusBarHeight < minKeyboardHeight) {
ShowKeyboard = false;
Toast.makeText(mContext,"鍵盤隱藏了",Toast.LENGTH_SHORT).show();
}
} else {
// 如果軟鍵盤是收起的狀態,并且height大于狀態欄高度,
// 說明這時軟鍵盤已經彈出
if (height - statusBarHeight > minKeyboardHeight) {
ShowKeyboard = true;
Toast.makeText(mContext,"鍵盤顯示了",Toast.LENGTH_SHORT).show();
}
}
}
};
** 需要特別指出的是,在某些手機上,比如華為mate8,底部會出現一個可以隨時隱藏與顯示的一行虛擬按鍵(Android雜亂生態的無奈??),所以我們要定義一個最小鍵盤高度。 **
//給最外層布局添加布局變化監聽
layoutMain.getViewTreeObserver().addOnGlobalLayoutListener(globalLayoutListener);
這樣根據ShowKeyboard值的變化 就能判斷鍵盤的顯示與隱藏了。
2.實現點擊其他區域隱藏鍵盤
這里利用的就是焦點,點擊其他區域,鍵盤會失去焦點,這個時候我們可以強制隱藏鍵盤,因為EditText 焦點已經缺失,某些隱藏鍵盤的方法可能失效。
inputText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager) mContext
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(layoutMain.getWindowToken(), 0);
}
}
});
3.實現滑動隱藏鍵盤,以及滑動到底部拉出鍵盤
這里主要實現方法是監聽用戶手勢,同時判斷鍵盤狀態,判斷webView是否滑動到底部了。
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (e1 == null || e2 == null) {
return false;
}
//判斷滑動距離,以及速度,如果鍵盤顯示中,隱藏鍵盤。
if (Math.abs(e2.getY() - e1.getY()) > flingHeight && Math.abs(velocityY) > flingspeed) {
if (ShowKeyboard) {
closeInputMethod(mContext);
}
}
float r= mWebView.getHeight();
// WebView總高度
float webViewContentHeight = mWebView.getContentHeight()*mWebView.getScale();
// WebView的現高度
float webViewCurrentHeight = (mWebView.getHeight() + mWebView.getScrollY());
// 這里是判斷 鍵盤是否顯示 滑動距離,以及是否滑動到底部。
if (!ShowKeyboard && e1.getY() - e2.getY() > getScreenHeight(mContext) / 10 && webViewContentHeight - webViewCurrentHeight <= 10) {
popInputMethod(inputText, mContext);
}
return false;
}
注意手勢監聽,不要遺忘以下操作:
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener
mGestureDetector = new GestureDetector(mContext, this);
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.dispatchTouchEvent(event);
}
最后看一下實現的效果圖:
實現效果圖