场景是一个表单提交信息界面,ScrollView套着一堆输入框edittext
当点击底部的输入框时,弹出的软键盘会遮挡住输入框,布局并未随着软键盘被顶上去
大家搜了一圈发现大部分都是让在manifests设置
android:windowSoftInputMode="stateVisible|adjustResize"
让activity去给软键盘腾出地方显示,但是并不是所有人都凑效,至少我的不是(崩溃)
既然顶不上去,那就让scrollview滚上去,但是滚上去需要让它知道滚到哪个位置,
就是先要获取到当前输入框View所在屏幕的位置,找了下控件有个getLocationOnScreen()方法
需要传入一个数组,来获取View所在屏幕位置,废话不说了上代码
emailText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
int[] position = new int[2];
emailText.getLocationOnScreen(position);
scrollView.smoothScrollTo(0, position[1]);
}
}, 200);
}
}
});
还有ScrollView里也要设置相应属性android:fitsSystemWindows="true"
<ScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:fillViewport="true">
这样就可以了,但是我总觉得跑了弯路,没有细追为什么设置android:windowSoftInputMode="stateVisible|adjustResize"
不会把布局顶上去的原因,希望哪位大佬知道,在评论里告诉我下,谢谢。
更新:
上面的写法有个问题,就是点了一个edittext后,会触发一次onFcousChange,但是再点一次就会不会触发,所以这样处理是有问题的。
第二个问题就是当软键盘弹出后,再触发onFcouschange,里面的getLocationOnScreen获取到的高度是软键盘顶上去的布局高度,所以会再次滚到布局的另一个位置
看着自己写的bug相当怪异,很抠笑
第二个问题我会记录一个历史高度来判定是否小于新获取的高度,如果小于新获取高度就把新高度赋值给历史高度
第一个问题就不用edittext的焦点事件,用点击事件来处理,但是第一次点击响应的是焦点事件,所以还要把焦点事件响应实现
但是处理都交给点击事件处理
@OnFocusChange({R.id.house_num_text, R.id.post_code_text, R.id.email_text}) public void focus(View view, boolean hasFocus) { if (hasFocus) click(); }
int originHeight = 0; @OnClick({R.id.post_code_text, R.id.email_text, R.id.house_num_text}) public void click() { new Handler().postDelayed(new Runnable() { @Override public void run() { int[] position = new int[2]; postCodeText.getLocationOnScreen(position); if (originHeight < position[1]) { originHeight = position[1]; scrollView.smoothScrollTo(0, position[1]); } } }, 200); }
这样看似很合理了,但是还是有个问题,就是软键盘关闭后,历史高度要重置回0。
这就需要去监听软键盘的弹出和关闭,
这里找了一个监听软键盘弹出关闭的类,网上太多了也不知道原作者是谁
import android.app.Activity; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; public class SoftKeyBoardListener { private View rootView;//activity的根视图 int rootViewVisibleHeight;//纪录根视图的显示高度 private OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener; public SoftKeyBoardListener(Activity activity) { //获取activity的根视图 rootView = activity.getWindow().getDecorView(); //监听视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变 rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //获取当前根视图在屏幕上显示的大小 Rect r = new Rect(); rootView.getWindowVisibleDisplayFrame(r); int visibleHeight = r.height(); System.out.println(""+visibleHeight); if (rootViewVisibleHeight == 0) { rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度没有变化,可以看作软键盘显示/隐藏状态没有改变 if (rootViewVisibleHeight == visibleHeight) { return; } //根视图显示高度变小超过200,可以看作软键盘显示了 if (rootViewVisibleHeight - visibleHeight > 200) { if (onSoftKeyBoardChangeListener != null) { onSoftKeyBoardChangeListener.keyBoardShow(rootViewVisibleHeight - visibleHeight); } rootViewVisibleHeight = visibleHeight; return; } //根视图显示高度变大超过200,可以看作软键盘隐藏了 if (visibleHeight - rootViewVisibleHeight > 200) { if (onSoftKeyBoardChangeListener != null) { onSoftKeyBoardChangeListener.keyBoardHide(visibleHeight - rootViewVisibleHeight); } rootViewVisibleHeight = visibleHeight; return; } } }); } private void setOnSoftKeyBoardChangeListener(OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { this.onSoftKeyBoardChangeListener = onSoftKeyBoardChangeListener; } public interface OnSoftKeyBoardChangeListener { void keyBoardShow(int height); void keyBoardHide(int height); } public static void setListener(Activity activity, OnSoftKeyBoardChangeListener onSoftKeyBoardChangeListener) { SoftKeyBoardListener softKeyBoardListener = new SoftKeyBoardListener(activity); softKeyBoardListener.setOnSoftKeyBoardChangeListener(onSoftKeyBoardChangeListener); } }
好了 在里面实现就简单了
SoftKeyBoardListener.setListener(this, new SoftKeyBoardListener.OnSoftKeyBoardChangeListener() { @Override public void keyBoardShow(int height) { } @Override public void keyBoardHide(int height) { originHeight = 0; } });
完美,测试未报任何不舒服的Bug。