首先键盘是什么,键盘其实是一个系统的dialog。当她出现的时候肯定会对屏幕的尺寸造成影响。所以屏幕会重绘什么啊,移动什么的。
特别特别重要的一点,调用系统显示键盘的方法时一定要先requestFocus这个editText的焦点。不然会出现一些怪异的事情,比如你掉了显示键盘,他也不会弹出。
关于键盘是android的一个比较大的问题,像搜狗,百度都是自己的输入法,这些都是需要对android的InputMethodManager进行深入的研究,当然首先肯定是看API
InputMethodManager
和INPUT_METHOD_SERVICE进行研究,由于这里只讨论工程上的如何快速开发一个app,所以我等搬砖工只进行应用上的研究。
首先来总结一下,android应用中有哪些关于键盘的需求。
1.随手打开一个app就会发现这样的需求
点击这个"写评论"就会弹出一个输入框,并且输入法需要将这个输入框顶上去。是这样的。
用户点击这个写评论触发了三个操作
1.EditText这个输入框出现,也就是visible。
2.键盘弹出。
3.键盘将这个EditText顶上去。
一个一个的解决。
第一步很简单,只需要在点击"写评论"的时候将这个EditText的状态visible即可。
第二,弹出,我们先说说怎么弹出,这时候就涉及到了InputMethodManager。现在具体说这个。
InputMethodManager,正如它的名字一样,是一个键盘的管理者,里面有一些和变量可以操作键盘。包括打开,强制关闭等操作。具体代码在github的demo里,注释写的很详细了。
第三,弹出的时候需要将这个visible的edittext顶上去,这时候设计到了一个属性叫windowSoftInputMode。
一定要注意理解windowSoftInputMode的每一个属性的意思。
一般是state属性和adjust属性一起用,之间用 | 隔开。
state表示的是软键盘在状态切换,比如activity跳转,view的重绘时候键盘的显示或者隐藏。
"stateUnspecified": 默认设置,没有什么用,依赖于theme的默认设置。
"stateUnchanged":当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示。
"stateHidden":当跳转一个activity的时候,键盘是hide的。注意是跳转而不是finish,也就说startActivity的时候当前键盘hide,但是当你finish当前activity,键盘不会消失。
"stateAlwaysHidden":不管什么,只要activity的主窗口获得焦点,键盘就hide。
"stateVisible":软键盘通常是可见的
"stateAlwaysVisible":上面的通常变成always。
"adjustUnspecified":默认设置,通常由系统自行决定是隐藏还是显示
"adjustResize": 会重新绘制view,onSizeChanged会重新调用,注意adjustPan这个方法不会调用。
"adjustPan":设置成adjustPan的时候键盘会去找当前界面的焦点,并始终焦点放在键盘的上方,使获得焦点的view可见。当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分
adjustResize 和 adjustPan 的目的很简单,他们两个都是做一切的努力想要为这个带有焦点的editText留出空间,让他出现,adjustPan采用的是一种平移屏幕的方式,将editText放在键盘上,adjustResize采用的是压缩屏幕的方式留出空间。为了留出空间,用心良苦啊。
其实布局顶起的正确与否,与一下因素有关:
当一个activity继承自Activity的时候:
非全屏模式下,一切正常。
全屏模式下,不管你是adjustXXX,最后的效果都是adjustPan。AndroidBug5497Workaround
非全屏模式一律不要加AndroidBug5497Workaround
当一个activity继承自AppCompatActivity的时候:
非全屏模式下,一切正常。
全屏模式下,也都是adjustPan效果。但是加了AndroidBug5497Workaround就可以实现adjustResize。但是测量的结果可能会有偏差。
这里要注意几点:(如下这张图片就是下面所讲的内容布局,写评论就是那个editText)
1.adjustResize的时候,系统会重新计算布局,onMeasure,onSizeChanged,onLayout都会重新执行,和adjustPan的区别方法是onSizeChanged会执行。
需要弹出的editText输入框不管怎么样都要放到原始布局的最下方。内容布局最好用ScrollView来包裹,这时候即使弹出也不会对内容布局造成任何影响。如果用别的布局代替ScrollView的话,内容布局就会按比例的压缩到一起,效果不好。原因是该Activity总是调整屏幕的大小以便留出软键盘的空间
2.一个怪异的问题是,当这个editText的background只有color,那么adjustResize不会有问题,但是adjustPan的时候,会遮挡住editText下部的一小部分,但是当这个background是一张.9图的时候显示正常,我猜想,当时介绍adjustPan的时候说了,他只是努力将移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分,他想着我你看到哪个光标也就是焦点了吧,那好我不移了。
目前来说,键盘还有几个问题没有得到优化,后续会继续进行。
1.全屏与adjustResize之间的冲突,设置了全屏之后自己变为adjustPan的效果了。(已解决,上面的内容里有)
2.底部有虚拟键盘的情况
3.沉浸式状态栏
2和3提到的问题,如果处理不了其实就是对于android的沉浸式,透明Navagation,还有android的window的view组成掌握的不熟悉,对AndroidBug5497Workaround不熟悉。。请到下几篇文章(详解AndroidBug5497Workaround,android的深层布局结构)里搞一搞,自己懂了原理自然就懂了。
4.键盘出现的时候布局闪动的问题,下一篇文章里会讲。具体的原理依据以下源码。
https://github.com/Jacksgong/JKeyboardPanelSwitch