Android 软键盘控制方法、以及开发中遇到的一些问题。

Android 提供了 windowSoftInputMode 属性来控制输入法软键盘窗口和 Activity 主窗口的交互,分为 窗口尺寸调整系列 和 输入法软键盘显示控制系列。

窗口尺寸调整系列:

该系列参数用来控制当软键盘弹起时,Activity 主窗口的调整策略,因为如果不调整主窗口,很可能会导致当前输入的控件被软键盘遮挡。

adjustPan:

Activity的主窗口并不会重新调整大小来为输入法腾出空间,而是窗口的内容会自动上下晃动来保证当前获得焦点的控件不会被键盘遮挡住,然后用户可以看见自己输入的内容。相比于 adjustResize 模式而言,它并不是很令人满意,因为用户必须关闭输入法来和被输入法遮挡住的控件进行交互。

adjustResize:

Activity的主窗口会重新调整大小来为输入法腾出空间。

adjustUnspecified:

当前模式并不会明确指定 Activity 使用adjustPan 或者 adjustResize ,系统会自动选择一个模式,选择结果是,如果当前 Activity 的 Window 中,有可以滚动自身内容的控件,比如 ScrollView,那么选择结果就是 adjustResize,因为它认为滚动可以使 Window 中的内容即使在一个很小的区域中也可以被看见。Activity 的默认模式就是这个模式。

adjustNoting:

Activity 的 Window 没有任何变化。

两种模式下,屏幕 - 主窗口 - 主窗口内容 - 软键盘 的关系如下:

具体效果如下:

没有滚动内容,adjustPan:

没有滚动内容,adjustResize:

没有滚动内容,adjustUnspecified == adjustPan

有滚动内容(ScrollView),adjustPan

有滚动内容(ScrollView),adjustResize

有滚动内容(ScrollView),adjustUnspecified == adjustResize

输入法软键盘显示控制系列:

该系列参数用来控制当一个包含 Window 的事物(Activity、Dialog等)展示在屏幕最前端时,软键盘的显示或者隐藏策略。

stateUnspecified:

系统根据当前具体情况,选择相应的模式。

stateUnchanged:

软键盘保持它的上一个状态(上一个Activity 或者 Dialog 在屏幕最前端时,软键盘的状态),不做变化,不管上一个状态是显示还是隐藏。

stateHidden:

当用户主动进入当前界面时,软键盘隐藏。离开上一个 界面,返回当前界面,不能算作 “主动进入”。被动进入时,保持上一个状态。

stateAlwaysHidden:

只要是用户进入该界面,就隐藏软键盘,不管是主动进入(新启动该界面),还是被动进入(离开上一个界面,返回到当前界面)。

stateVisible:

当用户主动进入当前界面时,显示软键盘。离开上一个 界面,返回当前界面,不能算作 “主动进入”。被动进入时,保持上一个状态。

stateAlwaysVisible:

只要是用户进入该界面,就显示软键盘,不管是主动进入(新启动该界面),还是被动进入(离开上一个界面,返回到当前界面)。

关于某些华为手机的一个Bug

今天遇到一个Bug,是这样的,在某些华为手机上面,除了第一次点击输入框,adjustPan 参数会生效(软键盘可以正常弹起输入框),后面从第二次开始,怎么点击,adjustPan 参数都无效。

布局模型大致如下:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="cn.hjf.inputtest.MainActivity">

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

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

            <View
                android:layout_width="match_parent"
                android:layout_height="400dp"
                android:background="#2b532b"/>

            <EditText
                android:layout_width="90dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_vertical"
                android:background="@null"
                android:gravity="center"
                android:inputType="numberDecimal"
                android:maxLength="8"
                android:minWidth="60dp"
                android:padding="5dp"
                android:text="0.00"/>

        </LinearLayout>

    </ScrollView>

</RelativeLayout>

效果是这样的:

经过漫长时间的排除(很辛苦),终于找到了Bug的触发临界点,就是下面这两句话:

android:gravity="center"
android:inputType="numberDecimal"

又经过了漫长时间的验证,得出一个结论:在某些华为机型上面,在这种布局模型下,EditText 中如果设置了 inputType 参数(不为 none),那么,在 gravity 取值为某些值得时候,会导致该问题的发生。大致情况如下:

红色表示失效,绿色表示有效(可以正常工作)。当这两个参数不指定的时候,可以工作,因为这两个属性默认值的组合是可以工作的,上图中的蓝色块。(备注:没有完全匹配所有情况,如有相似情况,可以按需匹配,查看结果)

在源码中可以找到这两个属性的默认值:

attrs.xml

 <!-- Default EditText style. -->
        <attr name="editTextStyle" format="reference" /> 

themes.xml

<item name="editTextStyle">@style/Widget.EditText</item>

styles.xml

<style name="Widget.EditText">
        <item name="focusable">true</item>
        <item name="focusableInTouchMode">true</item>
        <item name="clickable">true</item>
        <item name="background">?attr/editTextBackground</item>
        <item name="textAppearance">?attr/textAppearanceMediumInverse</item>
        <item name="textColor">?attr/editTextColor</item>
        <item name="gravity">center_vertical</item>
        <item name="breakStrategy">simple</item>
        <item name="hyphenationFrequency">normal</item>
    </style>

attrs.xml

 <!-- The type of data being placed in a text field, used to help an
         input method decide how to let the user enter text.  The constants
         here correspond to those defined by
         {@link android.text.InputType}.  Generally you can select
         a single value, though some can be combined together as
         indicated.  Setting this attribute to anything besides
         <var>none</var> also implies that the text is editable. -->
    <attr name="inputType">
        <!-- There is no content type.  The text is not editable. -->
        <flag name="none" value="0x00000000" />
..........
 
     /**
     * Special content type for when no explicit type has been specified.
     * This should be interpreted to mean that the target input connection
     * is not rich, it can not process and show things like candidate text nor
     * retrieve the current text, so the input method will need to run in a
     * limited "generate key events" mode, if it supports it. Note that some
     * input methods may not support it, for example a voice-based input
     * method will likely not be able to generate key events even if this
     * flag is set.
     */
    public static final int TYPE_NULL = 0x00000000;

一个需求

遇到一个需求,大致模型为:有一个界面,里面有一个 输入框 和 两个按钮,分别控制输入框中数字的加减,如下图所示:

每次输入框数字变化,不管是手动输入还是按钮控制,都会出发刷新工作,刷新时会弹出一个对话框。

然后需求是这样的,当手动输入的时候,这时触发刷新时,输入法是显示的,但是对话框显示然后消失后,输入法就被隐藏了。当用按钮控制的时候,是没问题的,因为整个过程,输入法都是隐藏的。所以需求就是,在对话框显示然后消失后,输入法能保持出发刷新时的状态。

解决问题:当把当前 Activity 设置为 stateUnchanged 的时候,并没有达到理想的效果,因为dialog所在的window,没有设置该属性,所以需要把dialog的window也设置为stateUnchanged,方法为:

getWindow().setSoftInputMode()

然后就可以了。

时间: 2024-10-06 18:06:17

Android 软键盘控制方法、以及开发中遇到的一些问题。的相关文章

完美解决android软键盘监听

最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况. 很不友好. 于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化. 借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中. 直接上代码.. 首先,在manifest文件中声明此Activity的windowSoftInputMode属性, 1 android:

android软键盘弹出引起的各种不适终极解决方案

很多写登录界面的开发者都会遇到一个问题:那就是在登录界面时,当你点击输入框时,下边的按钮有时会被输入框挡住,这个不利于用户的体验,所以很多人希望软键盘弹出时,也能把按钮挤上去.很多开发者想要监听键盘的状态,这无疑是一个很麻烦的做法. 我们可以在AndroidManifest.xml的Activity设置属性:android:windowSoftInputMode = "adjustResize" ,软键盘弹出时,要对主窗口布局重新进行布局,并调用onSizeChanged方法,切记一点

Android软键盘弹出,布局移动

在项目的androidmanifest.xml文件中界面对应的<activity>里加入 android:windowsoftinputmode="adjustpan"这样键盘就会覆盖屏幕.. 如果不想键盘覆盖屏幕,想让屏幕整体上移,就加入属性android:windowsoftinputmode="statevisible|adjustresize" Android软键盘弹出,布局移动,布布扣,bubuko.com

Android软键盘隐藏,遮挡EidtText解决办法

一.自动弹出软键盘 Timer timer=new Timer(); timer.schedule(new TimerTask() { public void run() { InputMethodManager inputMethodManager=(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.toggleSoftInput(0, InputMethodManage

【转载】android软键盘的一些控制

原文地址:http://blog.csdn.net/wang_shaner/article/details/8467688 "EditText + Button"  形成一个 "输入+按键响应" 的案例在android编程中是最常见不过的了. 但还有一些细节需要注意: 在EditText输入后,点击Button进行请求,软键盘应该自行消失 在EditText输入后,不点击Button进行请求,而是直接点击软键盘上的"回车",那么也应该能够正常响应

完美解决android软键盘监听1

最近在做应用性能调优,发现在一个包含有输入框的Activity中,当软键盘弹出的时候,如果直接finish掉此Activity,那么在返回到上一个Activity时,界面的渲染会由于软键盘没有及时的收起而出现卡顿的情况. 很不友好. 于是,本着geek的精神,做就做到极致,就尝试着对这一块做优化. 借助网上一些知识的分享,同时结合自己的理解,最终应用到项目中. 直接上代码.. 首先,在manifest文件中声明此Activity的windowSoftInputMode属性,      andro

Android 软键盘

一些重要常量含义: HIDE_IMPLICIT_ONLY     常量值: 1 (0x00000001) hideSoftInputFromWindow(IBinder, int)中的标志,表示如果用户未显式地显示软键盘窗口,则隐藏窗口. HIDE_NOT_ALWAYS         常量值: 2 (0x00000002) hideSoftInputFromWindow(IBinder, int)中的标志,表示软键盘窗口总是隐藏,除非开始时以SHOW_FORCED显示. RESULT_HIDD

Android软键盘弹出,界面整体上移的问题

AndroidManifest.xml文件中界面对应的<activity>里加入 android:windowSoftInputMode="adjustPan" 键盘就会覆盖屏幕 android:windowSoftInputMode="stateVisible|adjustResize" 屏幕整体上移 Android软键盘弹出,界面整体上移的问题

Android软键盘弹出,覆盖h5页面输入框问题

之前我们在使用vue进行 h5 表单录入的过程中,遇到了Android软键盘弹出,覆盖 h5页面 输入框 问题,在此进行回顾并分享给大家: 系统:Android 条件:当输入框在可视区底部或者偏下的位置 触发条件:输入框获取焦点,弹出软键盘 表现:软键盘 覆盖 h5页面中的输入框 问题分析: 1.发现问题:当前页面中box为flex布局,内容为上下固定高,中间自适应(中间区域内容过多会出现滚动条,input框在wrapper的底部),input获取焦点,手机键盘弹出,input未上移到可视区内,