先上个图:
1.gif
首先先科普一下,目前软键盘设置大概有那么几种状态:
1.软键盘弹出时,获取焦点的输入框会被顶起,整个界面往上移动,这种设置
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams. SOFT_INPUT_ADJUST_PAN);
2.软键盘弹出时,获取焦点的输入框被顶起,整个界面系统自动重新布局(挤压),这种设置
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams. SOFT_INPUT_ADJUST_RESIZE);
3.软键盘弹出时,整个界面不会变动,输入框也不会顶起,这种设置
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams. SOFT_INPUT_ADJUST_NOTHING);
但是,这几种解决方式都满足不了我的项目需求,我这边的需求是不仅输入框要显示出来,按钮也要显示出来(比如登录,注册这些),虽然说完全可以去跟pm讲价还价一顿,但是抱着和(song)睦(de)相(yi)处(bi)的想法,还是尝试去解决这个问题吧,最后还是征服了,顺便封了个库。
伸手党直接看这里
github:https://github.com/yoyoyaobin/PreventKeyboardBlockUtil
傻瓜式一键配置,不过目前刚完工,有些细节还没补充,之后会慢慢迭代,但是核心功能已经实现。
那就来说说解决思路吧
一开始脑海里的思路是:
1.设置一个软键盘监听事件,监听软键盘的弹出跟关闭
2.设置SOFT_INPUT_ADJUST_PAN的弹出方式
3.当软键盘弹出时,输入框被顶起,这时监听事件被触发,接下来去获取按钮的位置坐标以及软键盘高度
4.最后做最后一公里冲刺,设置布局的margin为:软键盘的Y坐标值减去按钮Y坐标值,使布局往上移动n像素,露出按钮
但是遇到了几个问题:
1.软键盘监听事件本质上是监听布局的变化,而当布局变化后坐标已经变得不准确,造成的后果就是:算出来的移动的值虽然是对的,但是系统自作主张的帮你也移动了一部分,并且是没法获取到的,所以移动出来的效果不好
2.如果是constraintlayout,给它设置负数的margin值是无效的
3.布局的方式有很多,可能针对你今天这个布局调出了这个效果,但是换一个布局可能就凉凉了,耦合性太强,不方便
4.margin的效果很差,layout直接刷的一下就弹了过去
最主要还是不准确的问题,因为受系统影响了,系统弹出软键盘时已经帮你移动了一部分,此时你自己的代码又执行了一次移动,直接就多出去了,而且这个系统帮移动的距离我至今不知道怎么去获取。
后来我修正了一下思路,想设置SOFT_INPUT_ADJUST_NOTHING,这样系统就不会去移动我的布局了,我自己来移动就行,结果发觉,这样根本监听不到软键盘的弹出,因为布局压根没有变化,那键盘的高度也就无从而知了。
皇天不负有心人,就在一整天的翻阅资料文章后,发现有一个方法可以
参考:https://github.com/siebeprojects/samples-keyboardheight
简单来讲,就是创建一个宽度为0、高度充满、弹出键盘的popupwindow,利用addOnGlobalLayoutListener去感知布局变化,算出键盘高度之后回调出去给外界使用
那,不就ok了?因为我设置了SOFT_INPUT_ADJUST_NOTHING,系统不会多事帮我移动,我又能获取到键盘高度,接下来就简单了,算出需要移动多少才会显示出按钮就行了。最后再把margin优化成属性动画的方式,把需要移动的布局改为内部自己去获取activity根布局(这样封装起来就不用外界传多一个布局对象了,同时也解决了margin方案的多种布局造成的不同效果烦恼)
整个流程下来,核心知识点只有三个:
1.系统软键盘设置对应的效果;
2.ViewTreeObserver的OnGlobalLayoutListener,监听视图变化;
3.属性动画;
ps:中间我还尝试使用ConstraintSet解决constraintlayout的移动问题,有兴趣研究的可以自行搜索ConstraintSet。
ok,收工,睡了睡了~
网友评论