今天解决了一个bug,虚拟键盘遮挡输入框。
解决这类问题有多种做法,但是也针对不同的项目情况做法也不同
出现的问题像在底部的输入框,当键盘弹出后输入框被遮住
解决思路有几种,需要有几点需要注意,稍后做一下解释,也是参考了好多网络资料再此表示感谢
1.一种时常见的简单直接在manifest中设置windowSoftInputModel="adjustPan|stateHidden"
这种在布局中用Scorllview套住即可。当然根据不通的主题设置有各种不同的注意点,网上有说ScrollView中fillViewPort=true的,有说fitSystemWindow=true的情况。下面是我的情况使用的。综合给大家些意见。
2.一种是,整个activity顶起,达到不被遮住的目的
public class AndroidBug5497Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity (Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private AndroidBug5497Workaround(Activity activity) {
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard/4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);// 全屏模式下: return r.bottom
}
}
这种是把整个activity上移达到不被遮挡,看代码知道是把activity的setContentView做处理
这种情况很方便,但是我改的别人bug使用无效,情况是项目主题设置了背景透明,这里这种方法有bug就是,当虚拟键盘弹出后,关闭键盘这时就会出现背景透明。如果没有设置主题背景透明这种情况是没有问题的也挺方便。
3.第二种就设置布局的padding值代码如下,当键盘谈起时把底部垫高,也算适合我这种情况,但是如果又在activity中设置全屏模式,我提到的所有情况都无效。
public class KeyboardPatch {
private Activity activity;
private View decorView;
private View contentView;
/**
* 构造函数
* @param act 需要解决bug的activity
* @param contentView 界面容器,activity中一般是R.id.content,也可能是Fragment的容器,根据个人需要传递
* */
public KeyboardPatch(Activity act, View contentView)
{
this.activity = act;
this.decorView = act.getWindow().getDecorView();
this.contentView = contentView;
}
/**
* 监听layout变化
* */
public void enable()
{
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
if (Build.VERSION.SDK_INT >= 19)
{
decorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
/**
* 取消监听
* */
public void disable()
{
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
if (Build.VERSION.SDK_INT >= 19)
{
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
}
}
private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
Rect r = new Rect();
decorView.getWindowVisibleDisplayFrame(r);
int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
int diff = height - r.bottom;
if (diff != 0)
{
if (contentView.getPaddingBottom() != diff)
{
contentView.setPadding(0, 0, 0, diff);
}
}
else
{
if (contentView.getPaddingBottom() != 0)
{
contentView.setPadding(0, 0, 0, 0);
}
}
}
};
}
这种可以根据你的情况设置contentview,看代码就是,虚拟键盘弹出时设置padding值垫高,关闭时padding值为零。
如果大家有想法欢迎给点意见