我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android软键盘windowSoftInputMode的使用与原理(使用篇)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android软键盘windowSoftInputMode的使用与原理(使用篇)

文章目录

前言

看了网上很多文章都没有很准确的说明windowSoftInputMode的几种模式的作用,而且大部分文章只是分析了一下如何使用并没有深入源码去分析原理,今天这篇文章就来分析一下Android软键盘windowSoftInputMode的各个模式的作用和原理,文章一共分为两篇,一是使用篇,二是原理篇,下面开始使用篇的讲解。

一、模式介绍

android:windowSoftInputMode=["stateUnspecified",           "stateUnchanged", "stateHidden",           "stateAlwaysHidden", "stateVisible",           "stateAlwaysVisible", "adjustUnspecified",           "adjustResize", "adjustPan"]

如上,windowSoftInputMode有六个stateXXX的值和三个adjustXXX的值。简单地说,state前缀的值控制软件输入法在Activity成为用户焦点时的可见性,adjust前缀控制其在窗口的显示方式。
两种值可组合使用。
可见性由两种:隐藏和显示
显示方式有两种:弹出软窗时,要么缩小内容部分,要么调整内容的位置,使其焦点控件处理可见窗口内。
每个值的意义,如下表(官方)

说明
"stateUnspecified"不指定软键盘的状态(隐藏还是可见)。 将由系统选择合适的状态,或依赖主题中的设置。

这是对软键盘行为的默认设置。

stateUnchanged当 Activity 转至前台时保留软键盘最后所处的任何状态,无论是可见还是隐藏。
stateHidden当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 隐藏软键盘。
stateAlwaysHidden当 Activity 的主窗口有输入焦点时始终隐藏软键盘。
stateVisible当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 显示软键盘。
stateAlwaysVisible当 Activity 的主窗口有输入焦点时始终显示软键盘。
adjustUnspecified不指定 Activity 的主窗口是否调整尺寸以为软键盘腾出空间,或者窗口内容是否进行平移以在屏幕上显露当前焦点。 系统会根据窗口的内容是否存在任何可滚动其内容的布局视图来自动选择其中一种模式。 如果存在这样的视图,窗口将进行尺寸调整,前提是可通过滚动在较小区域内看到窗口的所有内容。

这是对主窗口行为的默认设置。

adjustResize始终调整 Activity 主窗口的尺寸来为屏幕上的软键盘腾出空间。
adjustPan不调整 Activity 主窗口的尺寸来为软键盘腾出空间, 而是自动平移窗口的内容,使当前焦点永远不被键盘遮盖,让用户始终都能看到其输入的内容。 这通常不如尺寸调正可取,因为用户可能需要关闭软键盘以到达被遮盖的窗口部分或与这些部分进行交互。

二、可见性使用

通过上面的解释并不能很清晰的了解每个属性的具体作用,下面我来逐一详细介绍每个属性的作用。
为了方便展示我会创建两个Activity:InputActivity1和InputActivity2,并分别设置他们的属性进行操作。

1.stateUnchanged

当 Activity 转至前台时保留软键盘最后所处的任何状态,无论是可见还是隐藏。
这句话怎么理解呢?我们把两个Activity的windowSoftInputMode都设置为stateUnchanged。然后看下面的一个操作实例:
在这里插入图片描述

说明一下现象,首先进入InputActivity1时是没有显示软键盘的,在InputActivity1上呼出软键盘,然后跳转到InputActivity2,这时会发现InputActivity2上也会展示软键盘。继续看下面的操作实例:
在这里插入图片描述

在InputActivity1上没有呼出软键盘,然后跳转到InputActivity2,这时会发现InputActivity2上也没有展示软键盘。
通过这两个实例我们得出结论stateUnchanged不会改变软键盘的显示状态,如果软键盘之前是显示的,那么到其他Activity时也会显示,反之亦是如此。

刚才的实例都是前进到另一个Activity,如果是回退到上一个Activity呢?
在这里插入图片描述

首先InputActivity1没有显示软键盘的情况下跳转到InputActivity2,在InputActivity2手动唤起软键盘,之后回退到InputActivity1,可以发现这时软键盘也是显示的,由此可见无论是前进还是后退stateUnchanged都适用。

2.stateHidden

当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 隐藏软键盘。
同样的我们把两个Activity的windowSoftInputMode都设置为stateHidden。然后看下面的一个操作实例:
在这里插入图片描述
首先进入InputActivity1是没有显示软键盘的,手动唤起软键盘后跳转到InputActivity2,在InputActivity2上软键盘被隐藏了,这说明stateHidden起作用了,当用户向前导航到 Activity时软键盘会被隐藏
之后在InputActivity2上唤起软键盘并回退到InputActivity1,可以发现这时InputActivity1软键盘是显示的,由此可见只有前进的情况下stateUnchanged才生效。

3.stateAlwaysHidden

当 Activity 的主窗口有输入焦点时始终隐藏软键盘。
虽然同样是隐藏软键盘,但是stateAlwaysHidden的限定词少了,前面说到stateHidden必须是向前导航到Activity才生效,而stateAlwaysHidden就没有了这个限制,无论是向前还是向后都生效。我们来看一下实际操作,同样我们把两个Activity的windowSoftInputMode都设置为stateAlwaysHidden:
在这里插入图片描述
和上面的stateHidden同样的操作,但是在InputActivity2上唤起软键盘并回退到InputActivity1的时候,可以发现这时InputActivity1软键盘被隐藏了,由此可见无论是前进还是后退stateAlwaysHidden都适用。

4.stateVisible

当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 显示软键盘。
Visible和Hidden的意思一样,为了更清晰的看出他的作用,我们这次把InputActivity1设置为stateVisible,InputActivity2设置为stateHidden,然后看下面的一个操作实例:
在这里插入图片描述
刚进入到InputActivity1的时候软键盘就自动显示了,进入到InputActivity2的时候由于设置的stateHidden又隐藏了,再次返回InputActivity1的时候也没有显示出来,此可见只有前进的情况下stateVisible才生效。

关于Visible的两个属性有个需要注意的点:
在Android9.0以上的版本也就是API28,关于显示的两个属性都会失效,这一点在源码的注释中就说明了:

                public static final int SOFT_INPUT_STATE_VISIBLE = 4;                public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;

Applications that target {@link android.os.Build.VERSION_CODES#P} and later, this flag is ignored unless there is a focused view that returns {@code true} from {@link View#isInEditMode()} when the window is focused.

这篇文章详细介绍了失效的原因:https://blog.csdn.net/weimingjue/article/details/99738271
简单来说就是Android9.0之前一个Activity启动之后会自动获取焦点,而之后不会了,也就导致软键盘的显示失效了,解决方案是在Activity启动之后对需要输入的控件手动获取焦点view.requestFocus()

5.stateAlwaysVisible

当 Activity 的主窗口有输入焦点时始终显示软键盘。
这个就不多说了,直接看操作实例 :
在这里插入图片描述
相比与stateVisible,返回到InputActivity1的时候软键盘自动显示了。由此可见无论是前进还是后退stateAlwaysVisible都适用。

6.stateUnspecified

不指定软键盘的状态(隐藏还是可见)。 将由系统选择合适的状态,或依赖主题中的设置。
这是对软键盘行为的默认设置。

这种不指定具体方式的设置我就不详细说了(还挺复杂的),只要能掌握上面其他的几种设置应该就能满足日常的开发需要。

三、显示方式

先简单分析:
我们知道软键盘其实就是个Dialog,当键盘弹起的时,实际上当前能看到的是两个Window:1是Activity的Window,2是Dialog的Window。问题的关键是Dialog的Window展示遮盖了Activity的Window的部分区域,为了使EditText能够被看到,Activity的布局被向上顶上去,猜想Window 属性有控制是否顶上去的参数。还真有,这个参数就是WindowManager.LayoutParams.softInputMode。

1.adjustResize

始终调整 Activity 主窗口的尺寸来为屏幕上的软键盘腾出空间。
adjustResize实际上就是给根布局加Padding,padding的值就是软键盘的高度。 你可以直接给根布局加padding,效果是一样的。

我们使用如下布局代码进行测试:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/myviewgroup"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <ImageView        android:id="@+id/iv"        android:class="lazy" data-src="@drawable/test"        android:layout_marginTop="20dp"        android:layout_marginBottom="20dp"        android:layout_width="match_parent"        android:layout_height="300dp">    ImageView>    <EditText        android:hint="输入框2"        android:id="@+id/et2"        android:layout_gravity="bottom"        android:layout_marginTop="200dp"        android:layout_width="100dp"        android:layout_height="40dp">    EditText>LinearLayout>

将Activity设置为adjustResize,运行后效果如下:
在这里插入图片描述
可以看到布局并没有任何变化,输入框被隐藏,这是因为布局中的控件长度都是固定的,即使加了padding也没有任何效果。
接下来我们修改一下布局,将Imageview的高度设为layout_weight=1占满剩余屏幕。
修改后的内容如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/myviewgroup"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity">    <ImageView        android:id="@+id/iv"        android:class="lazy" data-src="@drawable/test"        android:layout_marginTop="20dp"        android:layout_marginBottom="20dp"        android:layout_weight="1"        android:layout_width="match_parent"        android:scaleType="fitXY"        android:layout_height="0dp">    ImageView>    <EditText        android:hint="输入框2"        android:id="@+id/et2"        android:layout_width="100dp"        android:layout_height="40dp">    EditText>LinearLayout>

在这里插入图片描述
可以看到不是固定长度的布局内容被顶上去并且高度被压缩了。

2.adjustPan

不调整 Activity 主窗口的尺寸来为软键盘腾出空间, 而是自动平移窗口的内容,使当前焦点永远不被键盘遮盖,让用户始终都能看到其输入的内容。 这通常不如尺寸调正可取,因为用户可能需要关闭软键盘以到达被遮盖的窗口部分或与这些部分进行交互。
adjustPan实际上就是布局整体向上滚动,这里无论什么样的布局都是一个效果,但是需要注意的是向上滚动的布局是根据当前焦点所在的位置确定的

使用和adjustResize一样的布局进行测试

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/myviewgroup"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="center_vertical"    android:background="@color/white"    android:orientation="vertical"    tools:context=".MainActivity">    <ImageView        android:id="@+id/iv"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:scaleType="fitXY"        android:layout_marginTop="20dp"        android:layout_marginBottom="20dp"        android:class="lazy" data-src="@drawable/test">ImageView>    <EditText        android:id="@+id/et2"        android:layout_width="100dp"        android:layout_height="40dp"        android:layout_marginTop="100dp"        android:hint="输入框2">EditText>LinearLayout>

在这里插入图片描述

3.adjustUnspecified

不指定 Activity 的主窗口是否调整尺寸以为软键盘腾出空间,或者窗口内容是否进行平移以在屏幕上显露当前焦点。 系统会根据窗口的内容是否存在任何可滚动其内容的布局视图来自动选择其中一种模式。 如果存在这样的视图,窗口将进行尺寸调整,前提是可通过滚动在较小区域内看到窗口的所有内容。这是对主窗口行为的默认设置。

adjustUnspecified实际上就是从adjustResize和adjustPan中选择一个,如果布局内容中有可滚动布局就选择adjustResize,如果没有就选择adjustPan,那么什么样的内容是可滚动内容呢?其实主要是isScrollContainer这个属性定义的,当布局的属性isScrollContainer设置为true的时候就代表这个布局是可以滚动的。

我们平时用的RecyclerView、ScrollView都是属于可滚动的内容,他们在初始化的时候就设置了这个属性

    public RecyclerView(Context context, @android.annotation.Nullable AttributeSet attrs, int defStyle) {        ...        setScrollContainer(true);        ...    }

对于普通的View,如果想要设置该属性有两种方法:

  1. 代码里:View.setScrollContainer(true)
  2. xml里: android:isScrollContainer=“true”

还用上面的布局进行测试

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/myviewgroup"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="center_vertical"    android:background="@color/white"    android:orientation="vertical"    tools:context=".MainActivity">    <ImageView        android:id="@+id/iv"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:scaleType="fitXY"        android:layout_marginTop="20dp"        android:layout_marginBottom="20dp"        android:class="lazy" data-src="@drawable/test">ImageView>    <EditText        android:id="@+id/et2"        android:layout_width="100dp"        android:layout_height="40dp"        android:layout_marginTop="100dp"        android:hint="输入框2">EditText>LinearLayout>

在这里插入图片描述
可以看到由于没有可滑动布局,这里选择了adjustPan将整个布局顶了上去,下面我们在ImageView上加上isScrollContainer属性:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/myviewgroup"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_gravity="center_vertical"    android:background="@color/white"    android:orientation="vertical"    tools:context=".MainActivity">    <ImageView        android:id="@+id/iv"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:scaleType="fitXY"        android:isScrollContainer="true"        android:layout_marginTop="20dp"        android:layout_marginBottom="20dp"        android:class="lazy" data-src="@drawable/test">ImageView>    <EditText        android:id="@+id/et2"        android:layout_width="100dp"        android:layout_height="40dp"        android:layout_marginTop="100dp"        android:hint="输入框2">EditText>LinearLayout>

在这里插入图片描述
这里就选择了adjustResize。

4.adjustNothing

不进行任何操作。

总结

以上是关于软键盘弹出、关闭、是否展示、软键盘高度、软键盘模式等效果的解析。
如果想了解以上效果的实现原理可以看下一篇文章Android软键盘windowSoftInputMode的使用与原理(原理篇)

来源地址:https://blog.csdn.net/shanshui911587154/article/details/124462145

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android软键盘windowSoftInputMode的使用与原理(使用篇)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android开发中怎么使用Dialog显示与隐藏软键盘

Android开发中怎么使用Dialog显示与隐藏软键盘?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。效果图:2.实现过程先说说最开始的实现方法:// 显示Dialogdial
2023-05-31

Android 解决使用SearchView时软键盘不支持actionSearch的问题

前言 变态问题常有,今年特别多,,, - - # 今天遇到的这个非处理不可,不然没法在HTC One S使用SearchView,其软键盘不支持action设置。 正文 问题设备: HTC One S searchable.xml<
2022-06-06

Spring的@Configuration使用与原理

这篇文章主要介绍了Spring的@Configuration使用与原理,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,需要的朋友可以参考下
2023-05-20

Android开发之Kotlin委托的原理与使用详解

我们常用的委托模式怎么使用?在 Java 语言中需要我们手动的实现,而在 Kotlin 语言中直接通过关键字 by 就可以实现委托,下面我们就一起看看不同种类的委托使用以及在 Android 常见的一些场景中的使用
2023-03-23

Android HandlerThread的使用及原理详解

一、HandlerThread的含义HandlerThread能够新建拥有Looper的线程。这个Looper能够用来新建其他的Handler。(线程中的Looper)需要注意的是,新建的时候需要被回调。 二、HandlerThread的用
2022-06-06

如何使用Android实现一个悬浮在软键盘上的输入栏

这篇文章主要介绍“如何使用Android实现一个悬浮在软键盘上的输入栏”,在日常操作中,相信很多人在如何使用Android实现一个悬浮在软键盘上的输入栏问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用A
2023-06-29

SpringBoot自动装配的原理与使用

在现代的软件开发中,依赖管理是一个关键的任务,随着应用程序规模的增长,手动管理对象之间的依赖关系变得越来越复杂,为了解决这个问题,SpringBoot提供了一种强大的功能,即自动装配,感兴趣想要详细了解可以参考下文
2023-05-20

Android 开发之Dialog中隐藏键盘的正确使用方法

Android 开发之Dialog中隐藏键盘的正确使用方法场景:弹出一个Dialog,里面有一个EditText,用来输入内容,因为输入时,需要弹出键盘,所以当Dialog消失时,键盘要一起隐藏。现在我们做一个自定义的DialogMyDia
2023-05-30

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录