1. 程式人生 > 其它 >android監聽軟鍵盤彈出彈回事件

android監聽軟鍵盤彈出彈回事件

技術標籤:【Android】android移動開發安卓軟鍵盤

概述

針對“軟鍵盤的遮擋”問題,最簡單的方式就是將activity的windowSoftInputMode設定成adjustResize或者adjustPan。

android:windowSoftInputMode="adjustResize"
android:windowSoftInputMode="adjustPan"

其效果一般如下:

如上圖,這樣設定後能保證“當前操作的佈局”在軟鍵盤之上。
但是實際業務場景,可能需要的是“將整塊佈局”設定在軟鍵盤之上,即Demo中的兩個輸入框和按鈕都需要在軟鍵盤之上。

如果需要實現這種需求,那麼開發者就必須要監聽軟鍵盤的彈出彈回事件,然後手動來調整佈局。

監聽原始碼

監聽實現的原理如下:

  • 監聽當前頁面contentView的佈局變化
  • 如果contentView上移,那麼是軟鍵盤彈出,如果contentView底部與decorview一樣,那麼是彈回。
public class KeyBoardListenerHelper {
  //constants
  private static final String TAG = "KeyBoardListenerHelper";
  //data
  private WeakReference<
Activity>
weakActivity = null;//避免記憶體洩漏,使用弱引用 private OnKeyBoardChangeListener onKeyBoardChangeListener; private final ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if
(!isActivityValid() || onKeyBoardChangeListener == null) { return; } try { Rect rect = new Rect(); weakActivity.get().getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); int screenHeight = weakActivity.get().getWindow().getDecorView().getHeight(); int keyBoardHeight = screenHeight - rect.bottom; onKeyBoardChangeListener.OnKeyBoardChange(keyBoardHeight > 0, keyBoardHeight); } catch (Exception e) { Log.e(TAG, "onGlobalLayout error:" + e.getMessage()); } } }; public KeyBoardListenerHelper(Activity activity) { if (activity == null) { return; } weakActivity = new WeakReference<>(activity); try { //設定後才可以監聽到軟鍵盤的彈出,此處不能設定SOFT_INPUT_ADJUST_UNSPECIFIED或者SOFT_INPUT_STATE_UNSPECIFIED,其他都可以. activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); View content = weakActivity.get().findViewById(android.R.id.content); content.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener); } catch (Exception e) { Log.e(TAG, "KeyBoardListenerHelper error:" + e.getMessage()); } } //在不使用的時候需要及時銷燬,避免記憶體洩漏或造成額外開銷 public void destroy() { Log.i(TAG, "destroy"); if (!isActivityValid()) { return; } try { View content = weakActivity.get().findViewById(android.R.id.content); content.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener); } catch (Exception e) { Log.e(TAG, "destroy error:" + e.getMessage()); } } public void setOnKeyBoardChangeListener(OnKeyBoardChangeListener listener) { Log.i(TAG, "setOnKeyBoardChangeListener"); this.onKeyBoardChangeListener = listener; } public interface OnKeyBoardChangeListener { void OnKeyBoardChange(boolean isShow, int keyBoardHeight); } public boolean isActivityValid() { return weakActivity != null && weakActivity.get() != null; } }

監聽呼叫

呼叫步驟:

  1. 在需要的地方初始化
  2. 根據自己需要在軟鍵盤彈出和彈回的時候控制佈局變化
  3. 在不使用的及時釋放不使用的監聽器
public class MainActivity extends Activity {

  private KeyBoardListenerHelper keyBoardListenerHelper;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    keyBoardListenerHelper = new KeyBoardListenerHelper(this);
    keyBoardListenerHelper.setOnKeyBoardChangeListener(
        new KeyBoardListenerHelper.OnKeyBoardChangeListener() {
          @Override public void OnKeyBoardChange(boolean isShow, int keyBoardHeight) {
            //此處可以根據是否顯示軟鍵盤,以及軟鍵盤的高度處理邏輯
            Log.i("testtest", "isShow: " + isShow + " keyBoardHeight:" + keyBoardHeight);
          }
        });
  }

  @Override protected void onDestroy() {
    super.onDestroy();
    if (keyBoardListenerHelper != null) {
      keyBoardListenerHelper.destroy();//避免記憶體洩漏,需要及時釋放
    }
  }
}