Android開發之監聽軟鍵盤狀態(彈出收回)

ShuSheng007發表於2018-08-08

版權申明】非商業目的註明出處可自由轉載
博文地址:https://blog.csdn.net/ShuSheng0007/article/details/81511764
出自:shusheng007

概述

在我們開發過程中,有時需要監聽手機軟鍵盤狀態,但是Android沒有這樣的API,所以需要我們自己處理。

實現方案

實現效果與原理

先上一張效果圖
這裡寫圖片描述
可以看到我們準確的監聽到了軟鍵盤的彈出與收起事件

首先我們應該思考,從鍵盤彈出與隱藏這個動作中我們可以獲得什麼有用的資訊呢?我們的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:我們獲取到了設定到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();
         }
     });
 }

note:此方式必須在彈出鍵盤時候,使頁面原有佈局發生變動,所以如果不起作用的話可以試著在AndroidManifest.xml檔案中設定android:windowSoftInputMode=”adjustResize|stateHidden“”

隱患

由於我們設定為佈局變動大於有效高度1/4就認為是由軟鍵盤引起的,當遇到鍵盤高度小於1/4,或者佈局由於設計原因會有高度變化大於1/4時都會出問題,但是這些情況都是極其罕見的。

相關文章