我们在开发的过程中很多时候都会遇到输入框会被输入法挡住看不到的情况。
解决版本当然有很多,Android给的设备两种模式的方法,很直接。但是不好用,问题也很多就不提了。
下面就说说我我的解决思路:
1,通过这个方法(.getViewTreeObserver().addOnGlobalLayoutListener)可以得到屏幕的宽度和输入法弹出的button值的变化来确定输入法是否弹出
//输入法到底部的间距(按需求设置)
final int paddingBottom = UIHelper.dipToPx(5);
mLlSava.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
mLlSava.getWindowVisibleDisplayFrame(r);
//r.top 是状态栏高度
int screenHeight = mLlSava.getRootView().getHeight();
int softHeight = screenHeight - r.bottom;//输入法弹出r.buttom的值会变小
if (softHeight > 100) {//当输入法高度大于100判定为输入法打开了
mLlSava.scrollTo(0, softHeight + paddingBottom );
} else {//否则判断为输入法隐藏了
mLlSava.scrollTo(0, paddingBottom);
}
}
});
这个方法可以解决大多数情况。
int softHeight = screenHeight - r.bottom;计算出输入法弹出的高度
然后将整个布局网上滑动, mLlSava.scrollTo(0, softHeight + paddingBottom );
输入法就不会挡住输入框了。
但是这也会有问题,输入框位置较高和较大的话。输入框会被滑出屏幕范围内,而被顶部给挡住。
十分尴尬呀。
2、这个原因是滑动把整个布局上移,(保存)一=以下下这块底部空间还是挺大的,要是这部分下移就好了。
接着再来一个知识点
Android里面提供了一些方法可以获取View在屏幕中的位置。
getLocationOnScreen ,计算该视图在全局坐标系中的x,y值,获取在当前屏幕内的绝对坐标(该值从屏幕顶端算起,包括了通知栏高度)。
getLocationInWindow ,计算该视图在它所在的widnow的坐标x,y值。
getLeft , getTop, getBottom, getRight, 这一组是获取相对在它父亲布局里的坐标。
注意:如果在Activity的OnCreate()事件输出那些参数,是全为0,要等UI控件都加载完了才能获取到这些数据。
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int[] location = new int[2];
v.getLocationOnScreen(location);
x = location[0];
y = location[1];
Log.d("test", "Screenx--->" + x + " " + "Screeny--->" + y);
v.getLocationInWindow(location);
x = location[0];
y = location[1];
Log.d("test", "Window--->" + x + " " + "Window--->" + y);
Log.d("test", "left:" + v.getLeft());
Log.d("test", "right:" + v.getRight());
Log.d("test", "Top:" + v.getTop());
Log.d("test", "Bottom:" + v.getBottom());
Log.d("test", "Width:"+v.getWidth());
Log.d("test", "Height:"+v.getHeight());
}
通过上面的方法不就可以知道所有view的位置吗,那么我知道屏幕的高度,view的位置高度。
那不就可以计算出到底要滑动多少位置吗,也可以计算正好把输入框的顶部滑动到屏幕顶部。哈哈哈。。。。随便计算了,随便滑。
//输入法到底部的间距(按需求设置)
final int paddingBottom = UIHelper.dipToPx(5);
mLlSava.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
mLlSava.getWindowVisibleDisplayFrame(r);
//r.top 是状态栏高度
int screenHeight = mLlSava.getRootView().getHeight();
int softHeight = screenHeight - r.bottom;//输入法弹出r.buttom的值会变小
int[] ints = new int[2];
mBtnSave.getLocationOnScreen(ints);
if (softHeight > 100) {//当输入法高度大于100判定为输入法打开了
//(screenHeight - ints[1]) 屏幕底部到保存按钮上边框的高度
int scrollToY = softHeight - (screenHeight - ints[1]);
if (scrollToY > 0) {//如果有问题这个地方要注意自己调整算出来,怕出问题就把ints[1] 换成 mBtnSave.getTop()
mLlSava.scrollTo(0, softHeight + paddingBottom - (screenHeight - ints[1]));
}
} else {//否则判断为输入法隐藏了
mLlSava.scrollTo(0, paddingBottom);
}
}
});
好了完美解决了。
还有部分手机会和输入法会有问题, 一下方法加个保险
SoftKeyBoardListener.setListener(this,object :SoftKeyBoardListener.OnSoftKeyBoardChangeListener{
override fun keyBoardShow(height: Int) {//height是键盘的高度
}
override fun keyBoardHide() {
}
})
import android.app.Activity;
import android.arch.lifecycle.GenericLifecycleObserver;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
public class SoftKeyBoardListener {
public interface OnSoftKeyBoardChangeListener {
void keyBoardShow(int height);
void keyBoardHide();
}
private View rootView;//activity的根视图
private int screenBottom;//纪录根视图的显示高度
private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener;
boolean isShow = false;//软键盘是否显示
private ViewTreeObserver.OnGlobalLayoutListener listener;
private SoftKeyBoardListener(Activity activity) {
int state = WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE & activity.getWindow().getAttributes().softInputMode;
switch (state) {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
isShow = true;
break;
}
//获取activity的根视图
rootView = activity.getWindow().getDecorView();
screenBottom = activity.getWindowManager().getDefaultDisplay().getHeight();
//监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变
listener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//获取当前根视图在屏幕上显示的大小
Rect r = new Rect();
rootView.getWindowVisibleDisplayFrame(r);
System.out.println("rect============" + isShow + "===" + r.toShortString() + "===" + screenBottom);
if (!isShow && screenBottom > r.bottom) {
isShow = true;
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardShow(screenBottom - r.bottom);
}
return;
}
if (isShow && r.bottom >= screenBottom) {
isShow = false;
if (onSoftKeyBoardChangeListener != null) {
onSoftKeyBoardChangeListener.keyBoardHide();
}
return;
}
}
};
rootView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
addLifeObServer(activity);
}
private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener;
}
public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) {
SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity);
softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener);
}
public void addLifeObServer(Activity activity) {
if (activity instanceof LifecycleOwner) {
LifecycleOwner owner = (LifecycleOwner) activity;
owner.getLifecycle().addObserver(new GenericLifecycleObserver() {
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (event == Lifecycle.Event.ON_DESTROY) {
if (rootView != null)
rootView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
}
});
}
}
public static void closeKeybord(EditText mEditText, Context mContext) {
InputMethodManager imm = (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
mEditText.setFocusable(false);
}
}