对网上【自定义输入框】的改动
2017-03-17 本文已影响114人
zzEND
开发APP的时候经常会遇到的一个需求就是“自定义一个输入框”,市面上几乎所有app的输入框基本都是他们自己开发的。
自定义布局并非难事,难的是当软键盘弹出时,如何保证你的输入框能自动被顶起。
作为一个新手,遇到问题先百度一下,果然很快就在网上找到了“解决方案”:
View decorView = getWindow().getDecorView();
View contentView = mEditText;// 此处的控件ID可以使用界面当中的指定的任意控件
decorView.getViewTreeObserver().addOnGlobalLayoutListener(getGlobalLayoutListener(decorView, contentView));
private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView) {
return 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);
}
}
}
};
}
这段代码你能很轻易的在网上找到,作用大概是:声明getGlobalLayoutListener()方法,传入你的手机屏幕与指定的控件。ViewTreeObserver会监听你的屏幕,当软键盘弹出时,屏幕可见高度(r.bottom)变小。计算屏幕高度与r.bottom的差值,即为软键盘的高度(diff)。将指定控件的paddingBottom设为diff,就实现了“自定义输入框位于软键盘上方”。同理,当软键盘消失时,paddingBottom设为0,输入框自动落回底部。
这段代码本身没有问题,在绝大多数情况下都可以正常使用。可是根据我的测试,在部分Android4.4的手机上,会出现bug,具体表现为“输入框移动的高度变为软键盘高度的两倍”。
具体原因不明,我初步怀疑是setPadding的的处理机制不同导致的bug。如果padding是从屏幕底部开始计算,则padding值等于软键盘高度是没问题的。可是如果padding是从屏幕可见区域开始计算的,那么此时不需要paddingBottom。
于是我改了一下控件位移的方式,不再使用setPadding。下面是我改动后的代码:
private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView){
return new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
Rect r = new Rect();
decorView.getWindowVisibleDisplayFrame(r);
int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
int diff = decorView.getHeight() - r.bottom;
if (diff != 0) {
if (contentView.getPaddingBottom() != diff) {
contentView.setY(r.bottom - contentView.getHeight());
}
} else {
contentView.setY(decorView.getHeight() - contentView.getHeight());
}
}
};
}
我这里仅仅是将setPadding改为了setY,直接指定空间的坐标高度,这样适配问题就解决了。注意Y值等于屏幕可见高度(r.bottom)减去控件高度( contentView.getHeight() )