软键盘弹出高度监听工具类
package com.iyao.inputmethodhelper;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.view.ViewTreeObserver;
/**
* 软键盘帮助类
* Created by HT on 2018/2/12.
*/
@TargetApi(14)
public class InputMethodHelper {
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener;
private OnInputMethodListener onInputMethodListener;
private Rect windowContentRect;
private Rect keyboardRect;
private InputMethodHelper(OnInputMethodListener listener) {
this.onInputMethodListener = listener;
}
private void onAttach(Activity activity) {
View decorView = activity.getWindow().getDecorView();
windowContentRect = getDisplayVisibleFrameHeight(decorView);
onGlobalLayoutListener = () -> {
Rect displayVisibleFrame = getDisplayVisibleFrameHeight(decorView);
if (keyboardRect == null) {
keyboardRect = new Rect(displayVisibleFrame);
}
keyboardRect.top = displayVisibleFrame.bottom;
keyboardRect.bottom = windowContentRect.bottom;
if (onInputMethodListener != null) {
onInputMethodListener.onInputMethodStatusChanged(keyboardRect, keyboardRect.height() != 0);
}
};
decorView
.getViewTreeObserver()
.addOnGlobalLayoutListener(onGlobalLayoutListener);
}
@RequiresApi(16)
private void onDetach(Activity activity) {
if (onInputMethodListener != null) {
activity.getWindow()
.getDecorView()
.getViewTreeObserver()
.removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
public static void assistActivity(Activity host, OnInputMethodListener onInputMethodListener) {
if (host == null) {
return;
}
InputMethodHelper methodHelper = new InputMethodHelper(onInputMethodListener);
host.getApplication().registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
if (host == activity && methodHelper.onGlobalLayoutListener == null) {
methodHelper.onAttach(activity);
}
}
@Override
public void onActivityResumed(Activity activity) {
if (host == activity && methodHelper.onGlobalLayoutListener == null) {
throw new IllegalStateException("assistActivity() must be called before onStart() called!");
}
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (activity == host) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
methodHelper.onDetach(activity);
}
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
}
}
});
}
public static void assistFragment(Fragment fragment, OnInputMethodListener onInputMethodListener) {
if (fragment == null) {
return;
}
InputMethodHelper methodHelper = new InputMethodHelper(onInputMethodListener);
fragment.getFragmentManager().registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() {
@Override
public void onFragmentViewCreated(FragmentManager fm, Fragment f, View v, Bundle savedInstanceState) {
if (f == fragment) {
methodHelper.onAttach(f.getActivity());
}
}
@Override
public void onFragmentViewDestroyed(FragmentManager fm, Fragment f) {
if (f == fragment) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
methodHelper.onDetach(f.getActivity());
}
f.getFragmentManager().unregisterFragmentLifecycleCallbacks(this);
}
}
}, false);
}
public static Rect getDisplayVisibleFrameHeight(View view) {
Rect r = new Rect();
view.getWindowVisibleDisplayFrame(r);
return r;
}
public static void toggleInputMethod(View token, boolean show) {
if (token == null)
return;
InputMethodManager manager = (InputMethodManager) token.getContext().getSystemService(Context
.INPUT_METHOD_SERVICE);
token.setFocusableInTouchMode(show);
token.setFocusable(show);
if (token instanceof EditText) {
((EditText) token).setCursorVisible(show);
}
if (show) {
if (!token.isFocused()) {
token.requestFocus();
if (token instanceof EditText) {
int length = ((EditText) token).getText().length();
((EditText) token).setSelection(length);
}
}
if (manager != null) {
manager.showSoftInput(token, SHOW_FORCED);
}
} else {
token.clearFocus();
if (manager != null) {
manager.hideSoftInputFromWindow(token.getWindowToken(), 0);
}
}
}
public interface OnInputMethodListener {
/**
* 软键盘弹出/收起监听
* @param keyboardRect 键盘弹出区域,宽,高
* left = keyboardRect.left
* top = keyboardRect.top
* right = keyboardRect.right
* bottom = keyboardRect.bottom
* width = keyboardRect.width()
* height = keyboardRect.height()
* @param show true 显示,false 隐藏
*/
void onInputMethodStatusChanged(Rect keyboardRect, boolean show);
}
}
处理随内容滚动的输入框遮挡问题(如包含在ScrollView或RecyclerView中的EditText)
InputMethodHelper.assistActivity(this, (keyboardRect, show) -> {
//1,获取当前焦点View
View currentFocus = getCurrentFocus();
//2,当键盘弹出,焦点View不为空(更严格的条件:焦点View就是需要处理的EditText),计算需要处理的被遮挡
//的高度,相对滚动该高度
if (show && currentFocus != null) {
int[] out = new int[2];
currentFocus.getLocationInWindow(out);
int offset = out[1] + currentFocus.getHeight() - keyboardRect.top;
if (offset > 0) {
//输入框被遮挡
scrollView.scrollBy(0, offset);
}
}
//3,计算键盘高度,处理内容区域可滚动距离少于遮挡高度的情况,保证滚动能够达到预期的效果
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) parent.getLayoutParams();
if (layoutParams.bottomMargin != keyboardRect.height()) {
layoutParams.bottomMargin = keyboardRect.height();
parent.requestLayout();
}
});
处理部分ViewGroup中含吸底输入框的View组件遮挡问题
InputMethodHelper.assistActivity(this, (keyboardRect, show) -> {
if (bottomView == null || (show && !Objects.equals(getCurrentFocus(), editView))) {
return;
}
LayoutParams layoutParams = (LayoutParams) bottomView.getLayoutParams();
int keyboardHeight = keyboardRect.height();
if (layoutParams.height != keyboardHeight) {
layoutParams.height = keyboardHeight + bottomView.getMinimumHeight();
bottomView.requestLayout();
}
});
或者
InputMethodHelper.assistFragment(this, (keyboardRect, show) -> {
if (bottomView == null || (show && !Objects.equals(getCurrentFocus(), editView))) {
return;
}
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)
bottomView.getLayoutParams();
int keyboardHeight = keyboardRect.height();
if (layoutParams.bottomMargin != keyboardHeight) {
layoutParams.bottomMargin = keyboardHeight;
bottomView.requestLayout();
}
});