作者丨ExampleCode
https://www.jianshu.com/p/6ab9c0507705
在Android應用的開發中,有一些需求需要我們獲取到輸入法的高度,但是官方的API並沒有提供類似的方法,所以我們需要自己來實現。
查閱了網上很多資料,試過以後都不理想。
比如有的方法通過監聽布局的變化來計算輸入法的高度,這種方式在Activity的配置中配置
為"android:windowSoftInputMode="adjustResize""時沒有問題,可以正確獲取輸入法的高度,因為布局此時確實會動態的調整。
但是當Activity配置
為"android:windowSoftInputMode="adjustNothing""時,布局不會在輸入法彈出時進行調整,上面的方式就會撲街。
不過經過一番探索和測試,終於發現了一種方式可以在即使設置為adjustNothing時也可以正確計算高度放方法。
GitHub地址:
https://github.com/siebeprojects/samples-keyboardheight/tree/master/app/src/main/java/com/siebeprojects/samples/keyboardheight
其實也就兩個類,我也做了一些修改,解決了一些問題,這裡也貼出來:
KeyboardHeightObserver.java
public interface KeyboardHeightObserver {
void onKeyboardHeightChanged(int height, int orientation);
}
KeyboardHeightProvider.java
public class KeyboardHeightProvider extends PopupWindow {
private final static String TAG = "sample_KeyboardHeightProvider";
private KeyboardHeightObserver observer;
private int keyboardLandscapeHeight;
private int keyboardPortraitHeight;
private View popupView;
private View parentView;
private Activity activity;
public KeyboardHeightProvider(Activity activity) {
super(activity);
this.activity = activity;
LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
this.popupView = inflator.inflate(R.layout.keyboard_popup_window, null, false);
setContentView(popupView);
setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
parentView = activity.findViewById(android.R.id.content);
setWidth(0);
setHeight(LayoutParams.MATCH_PARENT);
popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (popupView != null) {
handleOnGlobalLayout();
}
}
});
}
public void start() {
if (!isShowing() && parentView.getWindowToken() != null) {
setBackgroundDrawable(new ColorDrawable(0));
showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0);
}
}
public void close() {
this.observer = null;
dismiss();
}
public void setKeyboardHeightObserver(KeyboardHeightObserver observer) {
this.observer = observer;
}
private int getScreenOrientation() {
return activity.getResources().getConfiguration().orientation;
}
private void handleOnGlobalLayout() {
Point screenSize = new Point();
activity.getWindowManager().getDefaultDisplay().getSize(screenSize);
Rect rect = new Rect();
popupView.getWindowVisibleDisplayFrame(rect);
int orientation = getScreenOrientation();
int keyboardHeight = screenSize.y - rect.bottom;
if (keyboardHeight == 0) {
notifyKeyboardHeightChanged(0, orientation);
}
else if (orientation == Configuration.ORIENTATION_PORTRAIT) {
this.keyboardPortraitHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation);
}
else {
this.keyboardLandscapeHeight = keyboardHeight;
notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation);
}
}
private void notifyKeyboardHeightChanged(int height, int orientation) {
if (observer != null) {
observer.onKeyboardHeightChanged(height, orientation);
}
}
}
此處以在Activity中的使用進行舉例。
實現接口引入這兩個類後,在當前Activity中實現接口KeyboardHeightObserver:
@Override
public void onKeyboardHeightChanged(int height, int orientation) {
String or = orientation == Configuration.ORIENTATION_PORTRAIT ? "portrait" : "landscape";
Logger.d(TAG, "onKeyboardHeightChanged in pixels: " + height + " " + or);
}
在當前Activity定義成員變量,並在onCreate()中進行初始化
private KeyboardHeightProvider mKeyboardHeightProvider;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
...
mKeyboardHeightProvider = new KeyboardHeightProvider(this);
new Handler().post(() -> mKeyboardHeightProvider.start());
}
初始化完成後,我們要在Activity中的生命周期中也要進行處理,以免內存洩露。
@Override
protected void onResume() {
super.onResume();
mKeyboardHeightProvider.setKeyboardHeightObserver(this);
}
@Override
protected void onPause() {
super.onPause();
mKeyboardHeightProvider.setKeyboardHeightObserver(null);
}
@Override
protected void onDestroy() {
super.onDestroy();
mKeyboardHeightProvider.close();
}
此時我們就可以正確獲取的當前輸入法的高度了,即使android:windowSoftInputMode="adjustNothing"時也可以正確獲取到,這正是這個方法的強大之處,利用這個方法可以實現比如類似微信聊天的界面,流暢切換輸入框,表情框等。
推薦↓↓↓
涵蓋:程式設計師大咖、源碼共讀、程式設計師共讀、數據結構與算法、黑客技術和網絡安全、大數據科技、編程前端、Java、Python、Web編程開發、Android、iOS開發、Linux、資料庫研發、幽默程式設計師等。