android監聽軟鍵盤彈出彈回事件
阿新 • • 發佈:2021-02-12
技術標籤:【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;
}
}
監聽呼叫
呼叫步驟:
- 在需要的地方初始化
- 根據自己需要在軟鍵盤彈出和彈回的時候控制佈局變化
- 在不使用的及時釋放不使用的監聽器
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();//避免記憶體洩漏,需要及時釋放
}
}
}