Android 软键盘相关问题

1. windowSoftInputMode属性的使用

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

  • 当 Activity 成为用户注意的焦点时软键盘的状态 — 隐藏还是可见。
  • 对 Activity 主窗口所做的调整 — 是否将其尺寸调小以为软键盘腾出空间,或者当窗口部分被软键盘遮挡时是否平移其内容以使当前焦点可见。

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

<activity android:windowSoftInputMode="stateVisible|adjustResize" . . .复制代码

此处设置的值(“stateUnspecified”和“adjustUnspecified”除外)替换主题中设置的值。

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

系统默认值为:stateUnspecified|adjustUnspecified

上述是引用android官方文档的说明,但是这个并不能让我们理解所有内容。因此本次将具体探究这9个属性是如何影响。

1. stateUnspecified

android官方描述为:不指定软键盘的状态(隐藏还是可见)。 将由系统选择合适的状态,或依赖主题中的设置。这是对软键盘行为的默认设置。哪系统认为的合适的状态是什么样的呢?

我们采用如下布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content" />
</LinearLayout>复制代码

我们发现软键盘没有自动弹出,需要手动点击EditText后,键盘才会弹出来。
如果采用如下布局


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content" /></ScrollView>
</LinearLayout>复制代码

我们发现软键盘会自动弹出。这个就很奇怪了,为什么就加了一个ScrollView,难道是因为添加了ScrollView,软键盘就可以自动弹出来吗?我们看一下如下的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content" /></ScrollView>
</LinearLayout>复制代码

运行代码可以发现,这样软键盘也会不会自动弹出来。说明软键盘自动弹出和ScrollView没有直接关系。

如果我们采用如下布局,我们发现软键盘还是会自动弹出

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><ScrollViewandroid:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="测试"android:id="@+id/btn_test"/></LinearLayout></ScrollView>
</LinearLayout>复制代码

如何依旧采用上述的布局,但是我们在onCreate中加上如下代码

    Button button= (Button) findViewById(R.id.btn_test);button.setFocusable(true);button.setFocusableInTouchMode(true);button.requestFocus();button.requestFocusFromTouch();复制代码

我们发现软键盘将不会自动弹出来。

现在我们总结一下,当属性设置为stateUnspecified时,系统默认时不会自动弹出软键盘,但是当界面上有滚动需求时(有ListView或ScrollView等)同时有获得焦点的输入框软键盘将自动弹出来(如果获得焦点不是输入框也不会自动弹出软键盘)。

2. stateUnspecified

这个比较简单,进入当前界面是否弹出软键盘由上一个界面决定。如果离开上一个界面,键盘是打开,那边该界面键盘就是打开;否则就是关闭的.

3. stateHidden

这个也比较简单,进入当前界面不管当前上一个界面或者当前界面如何,默认不显示软键盘。

4. stateAlwaysHidden

这个参数和stateHidden的区别是当我们跳转到下个界面,如果下个页面的软键盘是显示的,而我们再次回来的时候,软键盘就会隐藏起来。而设置为stateHidden,我们再次回来的时候,软键盘讲显示出来。

5. stateVisible

设置这个属性,进入这个界面时无论界面是否需要弹出软键盘,软键盘都会显示。

6. stateAlwaysVisible

这个参数和stateAlwaysVisible的区别是当我们从这个界面跳转到下个界面,从下个界面返回到这个界面是软键盘是消失的,当回到这个界面软键盘依旧可以弹出显示,而stateVisible确不会。

上述6个属性定义的是进入界面,软键盘是否显示的。下面3个属性设置的是软键盘和界面显示内容之间的显示关系。

7. adjustResize,adjustPan

我们将这两个属性放在一起讨论。为了说明这个问题,我们先看如下的布局例子

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="3"android:background="@android:color/holo_red_dark"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="这个是一个测试"android:textSize="30sp" /></FrameLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="4"android:background="@android:color/holo_blue_light"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="这个是一个测试"android:textSize="30sp" /></FrameLayout><FrameLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:background="@android:color/white"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center" /></FrameLayout>
</LinearLayout>复制代码

adjustResize

adjustResize

adjustPan

adjustPan

由上面两张图我们可以知道,如果设置adjustResize属性,当键盘显示时,通过对界面主窗口的大小调整(压缩等)来实现留出软键盘的大小空间;如果设置adjustPan属性,当键盘显示时,通过对界面布局的移动来保证输入框可以显示出来。

8. adjustUnspecified

这个属性是根据界面中否有可以滚动的控件来判断界面是采用adjustResize还是adjustPan来显示软键盘。如果有可以滚动的控制,那可以将其理解为adjustResize,通过压缩界面来实现.但是是有一个前提的:可通过滚动在较小区域内看到窗口的所有内容。如果没有可以滚动的控件或者不符合前提条件,则是采用adjustPan,及移动布局来实现。

2. 软键盘的打开和关闭

软键盘的打开和关闭主要通过InputMethodManager实现。InputMethodManager关于打开关闭软键盘的方法主要有如下几个方法。

方法说明
hideSoftInputFromInputMethod(IBinder token, int flags)关闭/隐藏软键盘,让用户看不到软键盘,但是传入的token必须是是系统中token。
hideSoftInputFromWindow(IBinder windowToken, int flags)和下面hideSoftInputFromWindow方法一样,只是resultReceiver传入的值null
hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver)关闭/隐藏软键盘,和第一个方法的区别是他传入的token是系统界面中View窗口的token
showSoftInput(View view, int flags, ResultReceiver resultReceiver)和hideSoftInputFromWindow对应
showSoftInput(View view, int flags)同上面一个方法,但是默认的resultReceiver为null
showSoftInputFromInputMethod(IBinder token, int flags)和hideSoftInputFromInputMethod对应
toggleSoftInput(int showFlags, int hideFlags)该方法是切换软键盘,如果软键盘打开,调用该方法软键盘关闭;反之如果软键盘关闭,那么就打开
toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags)和上面一个方法一样,区别是传入的当前View的token
  1. 在上述方法中我们看到需要传入相关flags,相关flags有如下几个

    参数 | 说明
    -------------------|---
    HIDE_IMPLICIT_ONLY | 表示软键盘只有在用户未明确显示的情况才被隐藏
    HIDE_NOT_ALWAYS | 表示软键盘将一致隐藏,除非调用SHOW_FORCED才会显示
    SHOW_FORCED | 表示软键盘强制显示不会被关闭,除非用户明确的要关闭
    SHOW_IMPLICIT | 表示软键盘接收到一个不明确的显示请求。

  2. 我们经常看到用户传入的参数为0,不属于上述4个,那显示的是什么呢?其实如果传入的hideflag的话表示的是就是关闭软键盘,之前传入的参数不会改变,showflag的话表示的是SHOW_IMPLICIT

总结:

关闭软键盘的方法为

    public void hideKeyboard(View view) {((InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);}复制代码

打开关键盘的方法为

    public void OpenKeyboard(View view) {((InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_NOT_ALWAYS);}复制代码

3. 监听软键盘的打开和关闭

3.1 常规方法

监听软键盘的打开和关闭最常规的方法是监听View的层次结构,这个View的层次结构的发生全局性的事件如布局发生变化等我们可以通过调用getViewTreeObserver监听到布局的变化。代码实例如下:

    view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {// 虚拟键的高度int navigationBarHeight = 0;int resourceId = activityRootView.getContext().getResources().getIdentifier("navigation_bar_height", "dimen", "android");//判断是否有虚拟键if (resourceId > 0 && checkDeviceHasNavigationBar(activityRootView.getContext())) {navigationBarHeight = activityRootView.getResources().getDimensionPixelSize(resourceId);}// status bar的高度int statusBarHeight = 0;resourceId = activityRootView.getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");if (resourceId > 0) {statusBarHeight = activityRootView.getResources().getDimensionPixelSize(resourceId);}// 获得app的显示大小信息Rect rect = new Rect();((Activity)activityRootView.getContext()).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);//获得软键盘的大小:屏幕高度-(status bar的高度+虚拟键的高度+app的显示高度)int keyboardHeight = ((Activity) activityRootView.getContext()).getWindow().getDecorView().getRootView().getHeight() - (statusBarHeight + navigationBarHeight + rect.height());if (keyboardHeight>100 && !isSoftKeyboardOpened) {isSoftKeyboardOpened = true;notifyOnSoftKeyboardOpened(keyboardHeight);Log.d(TAG, "keyboard has been opened");} else  if(keyboardHeight <100 && isSoftKeyboardOpened){isSoftKeyboardOpened = false;notifyOnSoftKeyboardClosed();Log.d(TAG, "keyboard has been closed");}}} )复制代码

status bar是否存在其实也需要判断,但是因为app本身可以判断当前界面是否显示status的高度,所以上述代码默认status显示。

3.2 重写根布局的onMeasure

该方法使用于windowSoftInputMode被设置为adjustResize。如上文所致,adjustResize是采用压缩界面布局来实现软键盘可以正常显示。具体代码如下

public class KeyBoardFrameLayout extends FrameLayout {public KeyBoardFrameLayout(@NonNull Context context) {super(context);}public KeyBoardFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {super(context, attrs);}public KeyBoardFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {final int proposedheight = MeasureSpec.getSize(heightMeasureSpec);final int actualHeight = getHeight();int keyboardHeight = actualHeight - proposedheight;if (keyboardHeight > 100) {notifyOnSoftKeyboardOpened(keyboardHeight);} else if (keyboardHeight < -100) {notifyOnSoftKeyboardClosed();}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}复制代码

对比上述两种方法:

  1. 第一种方法的优点是不管windowSoftInputMode被设置为什么,都可以实现软键盘的开关键盘;第二种需要将上述的布局作为界面的根布局才能实现监听
  2. 第一种方法的缺点是事后监听,已当onLayout之后才会拿到监听,这个导致界面容易出现闪屏的情况;而第二种方法是在界面onLayout之前就拿到了监听,因此不会出现闪屏的情况。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git php框架,如何用Git安装TP框架

本篇文章主要给大家介绍如何用Git安装Thinkphp框架。关于TP框架的安装&#xff0c;想必大家都知道较为常见的方式是通过composer安装tp框架。首先简单的给大家介绍下Git和TP框架。Git是一个开源的分布式版本控制系统&#xff0c;可以快速&#xff0c;高效地处理从小型到大型项目…

C#EF中,使用类似于SQL中的% 模糊查询

最近在做项目的时候需要使用到模糊查询,但是后台使用EF写的 而不是ADO或者是Dapper,如果是这样的话,我们就可以使用Sql语句直接进行模糊查询 现在我们需要在LINQ中使用类似于模糊查询 在EF中有两个方法:StartsWith()和EndWith() StartsWith(): 在转到定义时 我们可以看见,这个方…

php snoopy视频教程,php的Snoopy类

用了两天这个类&#xff0c;发现很好用。获取请求网页里面的所有链接&#xff0c;直接使用fetchlinks就可以&#xff0c;获取所有文本信息使用fetchtext(其内部还是使用正则表达式在进行处理)&#xff0c;还有其它较多的功能&#xff0c;如模拟提交表单等。使用方法&#xff1a…

城轨列控系统

关于列控系统想问的问题 1&#xff09;列控系统的组成&#xff1f; 2&#xff09;城轨列控系统和列控系统有哪些区别&#xff1f; 3&#xff09;列控系统的设备图片&#xff1f; 4&#xff09;列控系统的作用&#xff1f; 1、地铁的供电部分&#xff1a; 参考&#xff1a;http:…

4、Orcal数据库dmp文件导入

1、CMD命令导入备份数据库dmp文件&#xff1a; 以上一篇博客提到的gdnh用户&#xff0c;我们需要在cmd窗口执行如下命令&#xff1a; imp gdnh/admin123orcl fileE:/createTable.dmp fully 截图说明&#xff1a; 导入成功的标志&#xff1a; 导入完成之后刷新表&#xff1a; 转…

iOS APP 安全测试

1、ipa包加壳 首先&#xff0c;我们可以通过iTunes 下载 AppStore的ipa文件(苹果 把开发者上传的ipa包 进行了加壳再放到AppStore中)&#xff0c;所以我们从AppStore下载的ipa都是加壳的&#xff0c;所以不能直接用来反编译。 得到ipa文件 可以分析APP 里包含的一些资源&#x…

oracle 与 client端执行结果不一致_Oracle -PLSQLDeveloper 13 数据库连接

关于oracle 及PLSQLDeveloper 13如何下载&#xff0c;安装流程不一一赘述&#xff0c;网络帖子很多&#xff0c;知乎直接搜索亦可。本次主要分享&#xff1a;学习前辈们关于安装流程中出现设置报错&#xff0c;应如何处理&#xff08;本人个例&#xff0c;通过网络找思路&#…

Redis——学习之路一(初识redis)

在接下来的一段时间里面我要将自己学习的redis整理一遍&#xff0c;下面是我整理的一些资料&#xff1a; Redis是一款依据BSD开源协议发行的高性能Key-Value存储系统&#xff08;cache and store&#xff09;&#xff0c;所以redis是可以查看源代码https://github.com/MSOpenTe…

css----实现checkbox图片切换

1、效果图 2、代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>checkbox</title><style type"text/css">label {width: 20px;font-size: 12px;cursor: pointer;}label i {display: inline-block…

【无删减】Python老司机收藏夹的17个国外免费学习网站

用Python编写代码一点都不难&#xff0c;事实上它一直被赞誉为最容易学的编程语言。如果你准备学习web开发&#xff0c; Python是一个不错的开始&#xff0c;甚至想做游戏的话&#xff0c;用Python来开发游戏的资源也有很多。这是快速学习这门语言的途径之一。许多程序员都把Py…

iframe vue 前进 后退_vue常见面试题

1、说说你对 SPA 单页面的理解&#xff0c;它的优缺点分别是什么&#xff1f;SPA&#xff08; single-page application &#xff09;仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成&#xff0c;SPA 不会因为用户的操作而进行页面的重新加载或跳转…

交叉熵与相对熵

熵的本质是香农信息量()的期望。 现有关于样本集的2个概率分布p和q&#xff0c;其中p为真实分布&#xff0c;q非真实分布。 按照真实分布p来衡量识别一个样本的所需要的编码长度的期望(即平均编码长度)为&#xff1a;H(p)。 如果使用错误分布q来表示来自真实分布p的平均编码长度…

menustrip

在对应菜单上点击鼠标右键&#xff0c;插入&#xff0c;SEPARATOR 就可以了&#xff0c;然后可以选中拖动位置。转载于:https://www.cnblogs.com/Echo529/p/6382302.html

什么是copyonwrite容器

2019独角兽企业重金招聘Python工程师标准>>> CopyOnWrite容器即写时复制的容器。通俗的理解是当往一个容器添加元素的时候&#xff0c;不直接往当前容器添加&#xff0c;而是先将当前容器进行Copy&#xff0c;复制出一个新的容器&#xff0c;然后新的容器里添加元素…

P2341 [HAOI2006]受欢迎的牛 强连通

题目背景 本题测试数据已修复。 题目描述 每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶 牛都是自恋狂&#xff0c;每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜 欢B&#xff0c;B喜欢C&#xff0c;那么A也喜欢C。牛栏…

spark mllib推荐算法使用

2019独角兽企业重金招聘Python工程师标准>>> 一、pom.xml <!-- 机器学习包 --><dependency><groupId>org.apache.spark</groupId><artifactId>spark-mllib_2.10</artifactId><version>${spark.version}</version>&…

R语言的自定义函数—字符组合

前两天写了几个函数&#xff0c;对里面收获到的一些东西做一些记录。 函数str_comb&#xff0c;用于输入一个字符串或数值向量&#xff0c;返回由向量中元素组成的不重复的长度小于向量长度的所有组合&#xff0c;结果用矩阵形式输出。 函数使用结果如下&#xff1a; 思路很简单…

oracle group by 两项,Oracle中group by 的扩展函数rollup、cube、grouping sets

Oracle的group by除了基本使用方法以外&#xff0c;还有3种扩展使用方法&#xff0c;各自是rollup、cube、grouping sets。分别介绍例如以下&#xff1a;1、rollup对数据库表emp。如果当中两个字段名为a&#xff0c;b,c。假设使用group by rollup(a,b)&#xff0c;首先会对(a,b…

机器学习基石13-Hazard of Overfitting

注&#xff1a; 文章中所有的图片均来自台湾大学林轩田《机器学习基石》课程。 笔记原作者&#xff1a;红色石头 微信公众号&#xff1a;AI有道 上节课主要介绍了非线性分类模型&#xff0c;通过非线性变换&#xff0c;将非线性模型映射到另一个空间&#xff0c;转换为线性模型…

oracle执行计划的rows不对,Oracle执行计划——all_rows和first_rows(n)优化器模式

Oracle执行计划——all_rows和first_rows(n)优化器模式0. 环境创建[sql]SQL> create usertest identified by test2 default tablespace users3 temporary tablespace temp4 quota unlimited on users;User created.SQL> grant createsession, resource, alter session t…