Android开发知识小集小技巧

让Android软键盘不遮挡布局

2017-01-20  本文已影响5072人  CP9

在Android UI中,我们常常会使用EditText,比如在一个ScrollView中放置多个EditText,如下图:

带有edittext的scrollview.png

当用户点击这个EditText时会触发软键盘,这个软键盘会把EditText以下的界面挡住:

被edittext遮挡的scrollview.png

android:windowSoftInputMode

Activity 的主窗口与包含屏幕软键盘的窗口的交互方式。 该属性的设置影响两个方面:

注意:该设置必须是下表所列的值之一,或者是一个“state...”值加上一个“adjust...”值的组合。在任一组中设置多个值(例如,多个“state...”值)都会产生未定义结果。各值之间使用垂直条 (|) 分隔。例如:

<activity android:windowSoftInputMode="stateVisible|adjustResize" . . . >
说明
"stateUnspecified" 不指定软键盘的状态(隐藏还是可见)。 将由系统选择合适的状态,或依赖主题中的设置。这是对软键盘行为的默认设置。
“stateUnchanged” 当 Activity 转至前台时保留软键盘最后所处的任何状态,无论是可见还是隐藏。
“stateHidden” 当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 隐藏软键盘。
“stateAlwaysHidden” 当 Activity 的主窗口有输入焦点时始终隐藏软键盘。
“stateVisible” 在正常的适宜情况下(当用户向前导航到 Activity 的主窗口时)显示软键盘。
“stateAlwaysVisible” 当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 显示软键盘。
“adjustUnspecified” 不指定 Activity 的主窗口是否调整尺寸以为软键盘腾出空间,或者窗口内容是否进行平移以在屏幕上显露当前焦点。 系统会根据窗口的内容是否存在任何可滚动其内容的布局视图来自动选择其中一种模式。 如果存在这样的视图,窗口将进行尺寸调整,前提是可通过滚动在较小区域内看到窗口的所有内容。这是对主窗口行为的默认设置。
“adjustResize” 始终调整 Activity 主窗口的尺寸来为屏幕上的软键盘腾出空间。
“adjustPan” 不调整 Activity 主窗口的尺寸来为软键盘腾出空间, 而是自动平移窗口的内容,使当前焦点永远不被键盘遮盖,让用户始终都能看到其输入的内容。 这通常不如尺寸调正可取,因为用户可能需要关闭软键盘以到达被遮盖的窗口部分或与这些部分进行交互。

从上表可以知道Activity的windowSoftInputMode默认是stateUnspecified|adjustUnspecified。这样我们就可以理解在scrollview中edittext会通过滚动在较小区域内看到窗口的所有内容,即表现为和adjustResize一样。

解决方案

  1. 修改受影响的activity的windowSoftInputMode属性
<activity
           android:name=".mall.TeaDetailsActivity"
           android:screenOrientation="portrait"
           android:windowSoftInputMode="stateHidden|adjustResize" />
  1. 然后设置EditText的点击事件
et.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                getKeyboardHeight();
            }
        });
  1. 判断软键盘是否弹出
private void getKeyboardHeight() {
        //注册布局变化监听
        getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //判断窗口可见区域大小
                Rect r = new Rect();
                getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
                //如果屏幕高度和Window可见区域高度差值大于整个屏幕高度的1/3,则表示软键盘显示中,否则软键盘为隐藏状态。
                int heightDifference = screenHeight - (r.bottom - r.top);
                boolean isKeyboardShowing = heightDifference > screenHeight / 3;
                if (isKeyboardShowing) {
                    changeScrollView();
                    //移除布局变化监听
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        getWindow().getDecorView().getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        getWindow().getDecorView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                }
            }
        });
    }
  1. 使ScrollView滚动到底部
    private void changeScrollView() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                //将ScrollView滚动到底  
                mScrollView.fullScroll(View.FOCUS_DOWN);  
            }
        }, 100);
    }

这样,我们的软键盘就会显示成如下图:

软键盘显示在布局之下.png

然而,这样还有个问题,就是第一个输入框被遮挡住了,我们可以考虑使用scrollTo方法让ScrollView只滑动到EditText的头部位置。

修改changeScrollView方法:

    private void changeScrollView() {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mScrollView.scrollTo(0, mScrollView.getChildAt(0).getHeight() - ll4.getHeight() - sll.getHeight());
            }
        }, 100);
    }

注意:mScrollView.getHeight()方法并不能获取到ScrollView的总高度,想要获取ScrollView的总高度可以使用mScrollView.getChildAt(0).getHeight()

如下图:


软键盘显示在布局之下并不遮挡输入框.png
上一篇下一篇

猜你喜欢

热点阅读