Android 软键盘之 windowSoftInputMode各种属性

windowSoftInputMode属性主要是用来设置窗口软键盘的交互模式的,这个属性会有两个影响:

1)当有焦点产生时,软键盘是隐藏还是显示。

2)是否减少活动主窗口大小以便腾出空间放软键盘。

这个属性一共有10个值,分别是:stateUnspecified、stateUnchanged、stateHidden、stateAlwaysHidden、stateVisible、stateAlwaysVisible、adjustUnspecified、adjustResize、adjustPan、adjustNothing

我们设置属性的时候。能够在这10个值里面选择一个。也能够用"state...|adjust"的形式进行设置。

1、stateUnspecified

未指定状态,当我们没有设置android:windowSoftInputMode属性的时候,软件默认采用的就是这种交互方式,系统会根据界面采取相应的软键盘的显示模式:

1)如果界面上只有文本和按钮的时候,软键盘就不会自动弹出;

2)如果界面上出现了获取了焦点的输入框时,

a、如果界面没有滚动需求,软键盘不会自动弹出;

b、如果界面有滚动需求(如界面中有RecyclerView、ScrollView等可以滑动的控件)时,软键盘会自动弹出。

2、stateUnchanged

状态不改变,当前界面的软键盘状态,取决于上一个界面的软键盘状态,如果从上一个界面跳转到当前界面的时候,软键盘是显示的,那么到了这个界面软键盘也是显示的;如果从上一个界面跳转到当前界面的时候,软键盘是隐藏的,那么到了这个界面软键盘也是隐藏的

3、stateHidden

状态隐藏,如果我们设置了这个属性,键盘状态就一定是隐藏的,不管上个界面是什么状态,也不管当前界面有没有输入的需求,就是不显示软键盘。

4、stateAlwaysHidden

状态隐藏,如果我们设置了这个属性,键盘状态就一定是隐藏的。和stateHidden效果几乎一样(暂未发现不同之处),比stateHidden隐藏范围更广。

 

5、stateVisible

状态显示,如果我们设置了这个属性,会把键盘召唤出来,即使在界面上没有输入框的情况下也会强制召唤出来。

 

6、stateAlwaysVisible

状态显示,这个属性也是将键盘召唤出来,与stateVisible属性小小的区别是:当我们设置了当前页面为stateVisible属性,如果当前的界面键盘是显示的,当我们点击按钮跳转到下个界面的时候,如果在新的页面软键盘隐藏起来,当我们再次回到当前页面的时候,键盘也是隐藏的;但是如果我们设置了当前页面为stateAlwaysVisible,跳转到下个页面,再回到当前页面的时候,软键盘也是会显示出来的。

估计stateHidden和stateAlwaysHidden的区别也类似。

从这開始就不是设置软键盘的显示与隐藏模式了,而是设置软键盘与软件的显示内容之间的显示关系。

不能滚动的布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="上部是头"
        android:textColor="@color/white"
        android:textSize="30sp"
        android:textStyle="bold"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="1"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="3"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="4"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="5"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="6"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="7"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="8"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="9"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="10"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="11"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="12"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="13"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="14"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="15"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="16"/>
        </LinearLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="下部是脚"
        android:textColor="@color/white"
        android:textSize="30sp"
        android:textStyle="bold"/>
</LinearLayout>

可以滚动的布局

<?xml version="1.0" encoding="utf-8"?>
<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SoftInputModeTestActivity">
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryDark"
            android:gravity="center"
            android:text="上部是头"
            android:textColor="@color/white"
            android:textSize="30sp"
            android:textStyle="bold"/>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="1"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="3"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="4"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="5"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="6"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="7"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="8"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="9"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="10"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="11"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="12"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="13"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="14"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="15"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="16"/>
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryDark"
            android:gravity="center"
            android:text="下部是脚"
            android:textColor="@color/white"
            android:textSize="30sp"
            android:textStyle="bold"/>
    </LinearLayout>
</ScrollView>

7、adjustUnspecified

未指定状态,这个是软键盘与页面之间显示关系的未指定状态、默认设置状态。这种状态下,系统会根据界面选择不同的模式,如果界面里有可滚动的控件,系统会缩小可以滚动的界面的大小来保证即使软键盘弹出了,也能够看到所有的控件;如果界面里没有可滚动的控件,那么软键盘可能就会盖住一些控件(布局的位置会发生变化,会让获取了焦点的控件显示出来,视情况隐藏可能会隐藏一些控件)。

原始状态

有滚动控件时 ,上下可以滚动展示所有内容

点击第一个条目

点击最后一个条目

没有滚动控件时,所有内容不可上下滚动

点击第一个条目

点击最后一个条目,整个页面头部被顶走

使用NestedScrollView会有不一样的效果

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".SoftInputModeTestActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryDark"
            android:gravity="center"
            android:text="上部是头"
            android:textColor="@color/white"
            android:textSize="30sp"
            android:textStyle="bold"/>


        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="1"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="2"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="3"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="4"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="5"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="6"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="7"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="8"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="9"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="10"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="11"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="12"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="13"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="14"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="15"/>

            <EditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="16"/>
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryDark"
            android:gravity="center"
            android:text="下部是脚"
            android:textColor="@color/white"
            android:textSize="30sp"
            android:textStyle="bold"/>
    </LinearLayout>
</android.support.v4.widget.NestedScrollView>

点击第一个条目,上下可以滚动,但是滚动不到底部

点击最后一个条目,滚动不到底部,滚动不到顶部,页面头部被顶走

8、adjustResize

调整大小状态,这个属性表示Activity的主窗口总是会被调整大小来保证软键盘的显示空间。如果界面中有可滑动控件,显示效果跟adjustUnspecified的滚动控件是ScrollView时的显示效果一样;如果界面中没有可滑动控件,软键盘可能会盖住一些控件(布局的位置不会发生变化,可能获取了焦点的控件被软键盘盖住)。

通过 hierarchy View 观察,decorView 大小本身并不会改变,但是我们的内容区 contentView (id = android.R.content) 会相应的缩小,为键盘的显示挪出空间。contentView 的下面为空白区域,软键盘就是覆盖在这个区域。

注意:adjustResize 只是调整 contentView 的大小,所以还是有可能覆盖掉 EditText。

adjustResize 最有用的是,这种模式可以轻松的获取到软键盘的高度,软键盘弹出后 contentView 高度变化的差值即为软键盘高度。

另外:这种模式可能会有个问题,当键盘消失时屏幕会出现一闪感觉有点难受。原因是键盘弹出时,键盘位置显示的是 windowBackground ,如果 windowBackground 为黑色而 Activity 背景为白色,当键盘消失时就会有闪动。解决办法是在 Activity 主题上添加一个 android:windowBackground 属性修改 windows 背景。

没有滚动控件时,点击第13个条目,上下不可滚动,13有焦点可输入,但不可见

9、adjustPan

如果设置了这个属性,当软键盘弹出的时候,系统会通过布局的移动,来保证用户要进行输入的输入框在用户的视线范围内。如果界面没有可滑动控件,显示效果和adjustUnspecified的没有滚动控件时效果一样;如果界面有可滑动控件,在软键盘显示的时候,可能会有一些内容显示不出来。显示效果和adjustUnspecified的可滚动控件为NestedScrollView时效果一样;

如果获取的焦点在页面上位置偏上,底部的一些内容可能显示不出来,被软键盘遮挡;如果获取的焦点在页面上位置偏下,顶部的一些内容可能显示不出来,被软键盘顶出屏幕。

Activity 窗口(DecorView) 大小不变。当获取到焦点的 EditText 位于屏幕下方,软键盘弹出会遮挡到 EditText 时,整个 DecorView 会往上移动,至于上移多少并不确定。一般是上移至使 EditText 刚好不被软键盘遮挡住为止。

10、adjustNothing

这种模式 Activity窗口不会做任何调整,contentView 大小也不会改变。

获取输入法高度方法:

给当前的activity覆盖一个宽度为0,高度为match_parent的PopupWindow,设置PopupWindow的mSoftInputMode为SOFT_INPUT_ADJUST_RESIZE,键盘弹出后,根据PopupWindow内容区高度的变化,来计算键盘弹出的高度。

public class HeightProvider extends PopupWindow implements OnGlobalLayoutListener {
    private Activity mActivity;
    private View rootView;
    private HeightListener listener;
    private int heightMax; // 记录popup内容区的最大高度

    public HeightProvider(Activity activity) {
        super(activity);
        this.mActivity = activity;

        // 基础配置
        rootView = new View(activity);
        setContentView(rootView);

        // 监听全局Layout变化
        rootView.getViewTreeObserver().addOnGlobalLayoutListener(this);
        setBackgroundDrawable(new ColorDrawable(0));

        // 设置宽度为0,高度为全屏
        setWidth(0);
        setHeight(LayoutParams.MATCH_PARENT);

        // 设置键盘弹出方式
        setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
    }

    public HeightProvider init() {
        if (!isShowing()) {
            final View view = mActivity.getWindow().getDecorView();
            // 延迟加载popupwindow,如果不加延迟就会报错
            view.post(new Runnable() {
                @Override
                public void run() {
                    showAtLocation(view, Gravity.NO_GRAVITY, 0, 0);
                }
            });
        }
        return this;
    }

    public HeightProvider setHeightListener(HeightListener listener) {
        this.listener = listener;
        return this;
    }

    @Override
    public void onGlobalLayout() {
        Rect rect = new Rect();
        rootView.getWindowVisibleDisplayFrame(rect);
        if (rect.bottom > heightMax) {
            heightMax = rect.bottom;
        }

        // 两者的差值就是键盘的高度
        int keyboardHeight = heightMax - rect.bottom;
        if (listener != null) {
            listener.onHeightChanged(keyboardHeight);
        }
    }

    public interface HeightListener {
        void onHeightChanged(int height);
    }
}
public class MainActivity extends AppCompatActivity {
    private EditText etBottom;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etBottom = findViewById(R.id.etBottom);

        new HeightProvider(this).init().setHeightListener(new HeightProvider.HeightListener() {
            @Override
            public void onHeightChanged(int height) {
                etBottom.setTranslationY(-height);
            }
        });
    }
}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/test" />

    <EditText
        android:id="@+id/etBottom"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:background="#ffabcdef" />

</RelativeLayout>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值