软键盘与PopupWindow的冲突
问题一:设置activity的SoftInputMode无效
在需求中,PopupWindow的布局需要EditText的layout居于底部,软键盘弹出时候要把EditText往上顶,但是布局整体不会往上走,然后大家都知道使用adjustResize属性,但是这个属于要对应到相应的Window上才会生效的。
错误且无效代码
//设置activity的属性
activity.getWindow().getAttributes().softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
////给Activity的window窗口设置软键盘展示属性
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
正确且有效的代码
mPopupWindow.setFocusable(true);
mPopupWindow.setOutsideTouchable(false);
mPopupWindow.setContentView(mContentView);
mPopupWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
//给PopupWindow的window窗口设置软键盘展示属性
mPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
mPopupWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, 0, 0);
知识点补充
在一个Activity上如何统计有多少个Window,大家都知道View的层级关系是Window -> DecorView,这个在Android艺术开发探索中有详细讲解,大家不明白的可以去查下。回归正题,如何统计一个Activity上的Window数量。
总数: window_all_number = iphoneWindow + 全部的PopupWindow的Window + 全部的Dialog的Window。
所以说各自的Window会管理各自的布局变化,上面我是想修改PopupWindow布局的ajustResize属性,但是却去修改了activity上的ajustResize属性,很显然这样子做popupWindow上是没有ajustResize属性,所以自然达不到要求的效果。
问题二:设置PopupWindow的ajustResize属性后,EditText的Layout一直在底部,不跟随软键盘的弹出往上顶,就是软键盘挡住了PopupWindow的底部布局
失败尝试方法1
因为我的activity的SoftInputMode属性是SOFT_INPUT_ADJUST_NOTHING,然后我强行在PopupWindow显示时候设置成SOFT_INPUT_ADJUST_RESIZE。
if (activity != null) {
activity.getWindow().getAttributes().softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
}
suprice MDF:失败是兵家常事,要学会分析原因,这里是因为PopupWindow和Activity的window不同,设置这个属性不会影响到PopupWindow的布局属性的,所以失败很正常。
失败尝试方法2
改变PopupWindow的初始化
//这种初始化需要后面制定宽高,我就替换成下面的代码
mPopupWindow = new PopupWindow(v, -2, -1);
//修改后
mPopupWindow = new PopupWindow(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
失败原因:PopupWindow初始化与设置ajustResize属性没太大关系,设置ajustResize属性是当软键盘弹出时候,系统会缩小当前布局的高度,从而适应软键盘的弹出。在失败两次之后,我觉得把目光锁定在了PopupWindow的宽高设置上。
问题二的解决办法
上面也分析说了将目光锁定在PopupWindow的宽高设置上,先看下代码中的宽高如何设置的。
mPopupWindow.setWidth(WindowManagerHelper.getDisplayWidth(mContentView.getContext()));
mPopupWindow.setHeight(WindowManagerHelper.getDisplayHeight(mContentView.getContext()));
代码中的mContentView.getContext是属于Activity的Context,因为你的mContentView是通过LayoutInflater.from(context).inflate去生成的。所以你可以想下,当你的PopupWindow的ajustResize起作用时候,是不是当前布局改变由Window控制,但是上面代码这样设置后,是将PopupWindow的大小改变选择权交给了Activity的Window去控制,所以当你设置ajustResize后,软键盘弹出,布局大小没有改变,因为PopupWindow的Window虽然接收通知,但是却改变大小权利不在它手上。
如何修改
- 改变PopupWindow初始化值
- 将PopupWindow的大小改变权限交换给PopupWindow的Window
//错误版本
mPopupWindow = new PopupWindow(v, -2, -1);
mPopupWindow.setWidth(WindowManagerHelper.getDisplayWidth(mContentView.getContext()));
mPopupWindow.setHeight(WindowManagerHelper.getDisplayHeight(mContentView.getContext()));
//修改版本代码
mPopupWindow = new PopupWindow(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
//上面是跟随父布局大小,就不需要手动设置宽高值
总结
View的层级管理和View的测量,布局,绘制过程都是android最有趣的地方,希望与大家一起加油,在项目中学习和成长。上面可能会存在理解不够深入的地方,希望大家可以指出让我完善自己的知识面。fighting……
推荐阅读