之前写过一篇文章 Android–>如何优雅的切换表情和键盘(原理), 没有看多的可以看看.

这个方案有一个问题, 当状态栏透明的时候, 就会出现问题. 而且也不支持在Dialog中使用.

实现方式也很简单, 但是代码逻辑很复杂, 不容易修改. 一不小心就会出错, 还找不到原因.

今天这篇文章, 让你焕然一新. 完全颠覆之前的方案.

前提,2个属性

android:windowSoftInputMode=“adjustResize”
android:fitsSystemWindows=“true”


会出现的坑:
如果通过简单的onSizeChange回调, 处理键盘弹出. 那么当状态栏透明之后, 这个方法是不会回调的.

因为, 当状态栏透明之后, 这个时候你的API已经满足了>=20. 这个时候:onApplyWindowInsets 此方法正好就是API 20的时候加入进来的.

从20开始, 系统改变了键盘弹出时, 布局的响应属性, 从原来的Height变化, 变成了最新的Padding变化.

也就是: 原来键盘弹出的时候, Layout的高度会变为原来的高度-键盘的高度;
而现在: Layout的高度不变, 但是PaddingBottom会变为键盘的高度.

这样就会导致onSizeChanged不会回调, 因为高宽都一样.

如果此时, 你要对不同的系统版本最适配, 提供对应的解决方案的话…那么,你将走向一条不归路.

其实,聪明的你, 应该也能想出解决方法.


以下是我的方案:

1:onMeasure
在测量内容高度和表情高度的时候, 根据键盘是否弹出, paddingBottom是否为空, 布局的height是否有变化.

决定内容的高度, 和 表情的高度. 主要是一定要确定内容的高度(要考虑键盘).

2:onLayout
有了高度, 就可以摆放内容布局和表情布局.

其实只要内容布局摆放合理, 表情布局在键盘弹出的时候可以任意摆放. 只要不影响内容就行.


就这么简单.


2019-8-20重构代码

  • 兼容低版本安卓系统
  • 支持最新版微信那样的动画
  • 支持多child布局
  • 支持padding处理
  • 支持SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN属性
  • 支持普通输入框切换到安全密码输入框
  • 支持布局preview
  • 内容布局支持wrap_conent, margin属性.(高度很小时, 默认从Gravity.BOTTOM开始布局)
  • 支持表情布局恢复.(如:显示键盘之前是表情布局, 那么隐藏键盘后就会显示表情布局)
  • 支持ViewPager+多Fragment中使用, 支持Activity+多Fragment中使用, 需要手动设置enableSoftInput, 任何时候, 只要保证有且仅有一个SoftInputLayout处于激活状态就行
  • 支持anim padding top属性
  • 支持动画回调, 可以入侵动画属性值

砖厂地址:
https://github.com/angcyo/ExKeyboardDemo