Android:windowSoftInputMethod软键盘弹出的问题浅析

来源:互联网 发布:python lambda * 编辑:程序博客网 时间:2024/06/18 13:37

一、浅析


很多时候在一些需要输入的界面上,我们需要呼出软键盘来打字。Android中会在AndroidMainfest.xml文件的 < activity />节点使用
android:windowSoftInputMode=”XXX”属性来设定呼出软键盘的属性。
下面就对一些属性做一个简单的列表说明。

  • “stateUnspecified” 软键盘的状态(是否它是隐藏或可见)没有被指定。系统将选择一个合适的状态或依赖于主题的设置。这个是为了软件盘行为默认的设置。

  • “stateUnchanged” 软键盘被保持无论它上次是什么状态,是否可见或隐藏,当主窗口出现在前面时。

  • “stateHidden” 当用户选择该Activity时,软键盘被隐藏——也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

  • “stateVisible” 软键盘是可见的,当那个是正常合适的时(当用户导航到Activity主窗口时)。

  • “stateAlwaysVisible” 当用户选择这个Activity时,软键盘是可见的——也就是,也就是,当用户确定导航到该Activity时,而不是返回到它由于离开另一个Activity。

  • “adjustUnspecified” 它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。

  • “adjustResize” 该Activity主窗口总是被调整屏幕的大小以便留出软键盘的空间。

  • “adjustPan” 该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。

二、举例


经常使用的是adjustPan和adjustResize,根据不同业务或者情景的需要也会用到像stateUnchanged(保持上次键盘状态)、stateHidden(隐藏键盘)等属性。

下面的例子是对adjustPan和adjustResize的一个比较。
注:adjustPan与adjustResize的最大不同就是,adjustResize会改变布局的大小,软键盘与当前Activity布局在同一层次,会将界面挤上去。

1、adjustPan

  • XML布局:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.david.keyborad">    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name="com.example.david.keyborad.MainActivity"            android:windowSoftInputMode="adjustPan">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.example.david.keyborad.MainActivity">    <com.example.david.keyborad.MyLayout        android:layout_width="match_parent"        android:layout_height="match_parent">        <EditText            android:id="@+id/edittext"            android:layout_width="150dp"            android:layout_height="wrap_content"            android:inputType="text"            android:hint="Hello World!" />    </com.example.david.keyborad.MyLayout></RelativeLayout>
  • 代码
package com.example.david.keyborad;import android.content.res.Configuration;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class MainActivity extends AppCompatActivity {    private  int cout = 0;    private static final String CONFIG_CHANGE = "Activity config count =";    private static final String ONATTACHE_TO_WINDOW = "Activity attach count =";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        Log.e(CONFIG_CHANGE+(cout++),"onConfigruationChanged");    }    @Override    public void onAttachedToWindow() {        super.onAttachedToWindow();        Log.e(CONFIG_CHANGE+(cout++),"onAttachToWindows()");    }}------------------------------------------------------package com.example.david.keyborad;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;import android.util.Log;import android.widget.LinearLayout;/** * Created by David on 2016/3/22. */public class MyLayout extends LinearLayout {    private int onDrawCount = 0;    private int onLayoutCount = 0;    private int onMeasureCount = 0;    private int onSizeChangedCout = 0;    private static final String ON_DRAW = "invoke Drawcount = ";    private static final String ON_MEASURE = " invoke Measure count = ";    private static final String ON_LAYOUT = "invoke layout count = ";    private static final String ON_SIZECHANGE = "invoked size count = ";    public MyLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        Log.e(ON_DRAW+(onDrawCount++),"onDraw() is invoked!");    }    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        Log.e(ON_SIZECHANGE+(onSizeChangedCout++),"onSizeChanged() is invoked! \n"+"newHight = "+h+"  newWidth = "+w+"  oldw = "+oldw+"  oldh = "+oldh );    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        Log.e(ON_MEASURE+(onMeasureCount++),"onMeasure() is invoked!\n"+"mesurewidth = "+widthMeasureSpec+"  mesureheight = "+heightMeasureSpec);    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        Log.e(ON_LAYOUT+(onLayoutCount++),"onLayout() is invoked!"+" left = "+l+"  top = "+t+" right = "+r+"bottom = "+b);    }}

我们来看看Log日志的输出,这是点击输入框之后的Log(初始化的时候没有复制进来):

03-22 11:23:54.668 27959-27959/com.example.david.testkeyboard E/ Measure invoke count =6: onMeasure() is invoked!                                                                                          mesurewidth = 1073742820  mesureheight = 107374332403-22 11:23:54.668 27959-27959/com.example.david.testkeyboard E/ Measure invoke count =7: onMeasure() is invoked!                                                                                          mesurewidth = 1073742820  mesureheight = 107374332403-22 11:23:54.668 27959-27959/com.example.david.testkeyboard E/layout invoke count =2: onLayout() is invoked! left = 42  top = 42 right = 1038bottom = 154203-22 11:23:54.817 27959-27959/com.example.david.testkeyboard E/ Measure invoke count =8: onMeasure() is invoked!                                                                                          mesurewidth = 1073742820  mesureheight = 107374332403-22 11:23:54.817 27959-27959/com.example.david.testkeyboard E/ Measure invoke count =9: onMeasure() is invoked!                                                                                          mesurewidth = 1073742820  mesureheight = 107374332403-22 11:23:54.817 27959-27959/com.example.david.testkeyboard E/layout invoke count =3: onLayout() is invoked! left = 42  top = 42 right = 1038bottom = 1542

稍微有点长,不过我们可以看到,点击输入框之后:
1、调用了4次onMeasure()测量Layout的大小,中间隔了一次onLayout()。
2、调用2次onLayout()方法设置Layout的方向、位置。

屏幕大小并没有改变,键盘是直接覆盖在当前Layout上面。

2、adjustResize

  • XML布局
    (只要改动 android:windowSoftInputMode=”adjustResize”)

这是点击输入框之后的输出日志:

03-22 11:31:17.394 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 4: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.394 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 5: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.394 27599-27599/com.example.david.testkeyboard E/invoke layout count = 1: onLayout() is invoked! left = 42  top = 42 right = 1038bottom = 154203-22 11:31:17.752 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 6: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.752 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 7: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.752 27599-27599/com.example.david.testkeyboard E/invoke layout count = 2: onLayout() is invoked! left = 42  top = 42 right = 1038bottom = 154203-22 11:31:17.950 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 8: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.950 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 9: onMeasure() is invoked!                                                                                           mesurewidth = 1073742820  mesureheight = 107374332403-22 11:31:17.961 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 10: onMeasure() is invoked!                                                                                            mesurewidth = 1073742820  mesureheight = 107374254903-22 11:31:17.961 27599-27599/com.example.david.testkeyboard E/ invoke Measure count = 11: onMeasure() is invoked!                                                                                            mesurewidth = 1073742820  mesureheight = 107374254903-22 11:31:17.961 27599-27599/com.example.david.testkeyboard E/invoked size count = 1: onSizeChanged() is invoked!                                                                                         newHight = 725  newWidth = 996  oldw = 996  oldh = 150003-22 11:31:17.961 27599-27599/com.example.david.testkeyboard E/invoke layout count = 3: onLayout() is invoked! left = 42  top = 42 right = 1038bottom = 767

我们发现,Log日志输入与上面adjustPan大致一样:
1、onMeasure方法调用了几次
2、onLayout方法也调用了几次

但是最大的不同在于,adjustResize属性之后会调用onSizeChanged方法,说明布局的大小发生了改变。同时我们也可以看到,newHeiht = 725,而oldHeight=1500。这个就是adjustResize与adjustPan的不同之处,具体来说大家都建议采用adjustResize属性,这样可以不妨碍用户在输入的时候浏览其他的内容。不过有些时候也需要adjustPan来覆盖在当前界面上以使得用户聚焦于输入当前的内容。

还有其他的属性还没有使用过,以后使用到了再一一说明,我觉得根据需求来找自己想要的效果是最好的。

0 0