欢迎转载,转载请注明出处:https://editor.youkuaiyun.com/md/?articleId=107068953
写在前面
老规矩,不想看文章的同学可以直接移步到Github
首先跟大家说声抱歉,距离上一篇文章CEventCenter将近一年了,最近才稍微有点空闲的时间可以写写博客,工作实在太忙,抱歉哈。
近期在开源一款即时通讯App,由于之前发布的NettyChat属于封装的一个Module,很多想基于Netty+TCP+Protobuf开发IM类App的同学不知道要怎么上手,而且群里以及掘金上也有很多同学想要聊天类的UI以及消息持久化、离线消息之类的处理逻辑代码等,所以决定从零开始,带领大家开发一款优秀的IM App,会包含ims_kula(基础通信模块)、KulaChat(基于ims开发的App)以及kulachat-server(Java服务端),将会是一个完整项目,敬请期待~
相信不少同学都踩过Android系统键盘处理的坑,尤其是自己开发过IM App的同学,在处理聊天会话页的键盘弹起、表情切换、输入法切换、更多模块切换等,往往会遇到键盘挤压布局、切换闪动及切换效果比较生硬之类的问题,我也有幸遇到过,从网上找了很多种方法,但效果不尽如人意,于是决定自己自己动手撸一个。接下来,我将带领大家,算了,废话不多说,我们直接开始。
效果对比
-
微信
-
KulaKeyboard
gif质量比较差,大家将就着看一下。从以上效果对比,我们可以注意几个点:
- 键盘首次弹出时,是有动画效果的,可以看到RecyclerView也跟着向上平移;
- 从输入法到表情切换时,由于表情面板比输入法稍高,可以看到键盘消失的同时,表情面板显示了,同时RecyclerView再整体向上平移了一段距离;
- 同上,从表情面板切换到输入法时,也有动画效果;
- 输入法或表情面板收起时,RecyclerView向下平移;
- 表情面板右下角,由于需要显示发送及删除按钮,所以最后两行的最后两个表情总是隐藏的,除非滑动到底部才全部显示。
接下来,我们来分析一下细节。
细节分析
键盘高度获取
windowSoftInputMode
在AndroidManifest.xml的节点,可以设置windowSoftInputMode属性,取值分别是以下10种:
- stateUnspecified
- stateUnchanged
- stateHidden
- stateAlwaysHidden
- stateVisible
- stateAlwaysVisible
- adjustUnspecified
- adjustResize
- adjustPan
- adjustNothing
其中,以state开头的都是设置软键盘的显示与隐藏的模式,我们无须关心,我们需要关心的是后面4个以adjust开头的属性,这4个属性是设置软键盘与显示内容之间的关系,下面我们来分析一下这4个属性,以及分别设置一下看看效果:
- adjustUnspecified
- 说明
默认值。不指定是否Activity的主窗口是否调整大小来为软键盘腾出空间或是否平移窗口内容来显示内容焦点(EditText
)。如果窗口内容存在可滚动的控件(比如RecyclerView
),那么系统将会选择adjustResize
模式将窗口调整大小(重绘RecyclerView
)。如果不存在可滚动的控件,那么系统将会将窗口整体向上平移以显示软键盘。也就是说,如果windowSoftInputMode
设置为adjustUnspecified
或者不指定任何属性时,系统将会在adjustResize
和adjustPan
中选择合适的一种。 - 效果展示
- 不包含可滚动的控件
- 包含可滚动的控件
- 不包含可滚动的控件
- 说明
- adjustResize
- 说明
Activity的主窗口总是调整大小来为软键盘腾出空间。如果主窗口存在可滑动的控件,那么系统将会调整该控件大小。如果不存在可滑动的控件,那么系统将会使主窗口布局进行压缩。 - 效果展示
- 不包含可滚动的控件
- 包含可滚动的控件
- 不包含可滚动的控件
- 说明
- adjustPan
- 说明
主窗口的内容焦点(EditText
)如果处在软键盘的高度覆盖的区域时,主窗口自动向上平移直至软键盘不遮挡内容焦点为止,使用户总能看到输入内容的部分。 - 效果展示
- 不包含可滚动的控件
- 包含可滚动的控件
- 不包含可滚动的控件
- 说明
- adjustNothing
- 说明
不作任何反应,不关心软键盘是否遮挡内容焦点(EditText
)。 - 效果展示
- 不包含可滚动的控件
- 包含可滚动的控件
- 不包含可滚动的控件
- 说明
以上属性说明,大部分参照网上的介绍加入自己的理解,希望能通俗易懂。
切换动画
从上述属性说明及效果展示可以看到,虽然设置adjustResize
可以实现软键盘弹出及输入面板切换到表情面板时Activity主窗口的RecyclerView
通过重绘去调整大小以适应,但同时也可以看到软键盘弹出时几乎没有任何动画过渡效果,界面切换非常生硬。当然网上也有不少人的实现方式是使表情面板高度和软键盘一致,这样在输入法面板和表情面板来回切换时避免界面切换效果比较生硬的问题,但软键盘弹出的效果还是非常生硬。
那么,有没有一种方法可以使切换效果更自然、体验更好呢?答案是肯定的。卖个关子,先听我把最后一个点说完,我们再来分析一下怎么实现。
利用不可见的PopupWindow获取键盘打开状态及键盘高度
Android系统没有提供API可以让我们获