关于Android键盘遮挡

事件

应对软键盘遮挡的问题,可以处理四个不同的事件,事件和调用顺序如下:
- onSizeChanged(Activity需要是AdjustResize的)
- onLayout(不用监听onMeasure,回调的位置太多了)
- addOnLayoutChangeListener监听layout的回调事件
- getViewTreeObserver().addOnGlobalLayoutListener监听全局的layout事件

问题

  • 在某些手机上,AdjustResize会导致键盘动画时闪一下黑底或者stack中下一个Activity的部分页面。非常尴尬。
  • 这个listener是个不会被销毁的引用,会有内存泄露。特别是绝大部分都是内部类的情况下,简直了。
  • 为了获得全局的可见空间,会调用getWindowVisibleDisplayFrame。这个官方文档中标明了,可能会有性能问题。
  • 如果要更改某些View的大小,很可能会出现在layout中requestLayout的尴尬场景。

怎么办

如何防露底

实现对View的AdjustResize。AdjustResize实际上就是在getWindow().getDecorView().getWindowVisibleDisplayFrame()变化时,调整Activity的RootView的LayoutParams。
为了避免直接使用AdjustResize会导致键盘动画过程中的露底问题,需要避免使用AdjustResize,而使用AdjustPan实现对Activity中某个View调用。这样动画过程中漏出来的是Activity的RootView,不会露底。

如何监听变化

一般都是说用globalLayoutListener,未尝不可,但是一定要注意removeListener,否则一定会影响性能,同时有可能出现内存泄露。
可以使用开头提到的其他三种方法。如果不想继承,比较好用的是给RootView设置一个OnLayoutChangeListener。但是,如果不使用AdjustResize,listener的回调参数是无用的;对RootView调用下面这几个函数也是没用的:

  • getDrawingRect
  • getGlobalVisibleRect
  • getLocalVisibleRect

也就是说,只能用getWindowVisibleDisplayFrame。
由于这个RootView是Activity维护的,当Activity可回收的时候,RootView一定可以回收,RootView持有的Listener,以及内部类间接持有的Activity都可以回收了,这样就不会有内存泄露了。

在大索尼上居然有兼容性问题,globalLayoutListener是ok的,目测是在做显示优化的时候如果大小不变就不进行layout,或者是硬件加速的鬼。
其他坑
  • 不要更改RootView大小,否则会露底。
  • 不要更改被addOnLayoutChangeListener的View的LayoutParams,因为setLayoutParams会调用requestLayout,进而会重新调用OnLayoutChangeListener。
  • 在OnLayoutChangeListener内部尽量早做判断终止逻辑,这个回调的执行实在是太多了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值