PopupWindow 系统6.0以上 setOutsideTouchable失效分析
来源:互联网 发布:短信猫用什么网络 编辑:程序博客网 时间:2024/06/06 11:02
一、PopupWindow是什么?
开发中可能弹框类使用最多的就是PopupWindow和Dialog,那么PopupWindow是什么呢?根据PopupWindow源码注释解释为:
* <p> * This class represents a popup window that can be used to display an * arbitrary view. The popup window is a floating container that appears on top * of the current activity. * </p>可以理解为弹出窗口,可以用来显示任意视图。弹出窗口是依附于当前Activity的。使用PopupWindow控件可以更加灵活的用于减少Activity使用设计的时候,比如游戏SDK开发的时候就尽量减少Activity的使用,再次封装即可做到不错的效果。
二、PopupWindow使用时问题?
PopupWindow原理不再分析,因为业务需求使用PopupWindow创建窗口,如果PopupWindow中需要使用EditText,必须设置:
popWindow.setOutsideTouchable(false);popWindow.setFocusable(true);//设置焦点生效
这样设置焦点可以获取,那么问题出现了,经测试6.0系统之前setOutsideTouchable设置为false 效果生效,但是在6.0之后的系统,就会出现失效。这样就需要看下6.0系统后的PopupWindow;入点查看setOutsideTouchable的原理:
/** * <p>Controls whether the pop-up will be informed of touch events outside * of its window. This only makes sense for pop-ups that are touchable * but not focusable, which means touches outside of the window will * be delivered to the window behind. The default is false.</p> * * <p>If the popup is showing, calling this method will take effect only * the next time the popup is shown or through a manual call to one of * the {@link #update()} methods.</p> * * @param touchable true if the popup should receive outside * touch events, false otherwise * * @see #isOutsideTouchable() * @see #isShowing() * @see #update() */ public void setOutsideTouchable(boolean touchable) { mOutsideTouchable = touchable; }
方法的大概意思:触摸窗口外的事件,默认为false,这样理解,设置setOutsideTouchable后应该是有效果的,但是6.0之后系统为什么没有效果:
private int computeFlags(int curFlags) { curFlags &= ~( WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH); if(mIgnoreCheekPress) { curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; } if (!mFocusable) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; if (mInputMethodMode == INPUT_METHOD_NEEDED) { curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } } else if (mInputMethodMode == INPUT_METHOD_NOT_NEEDED) { curFlags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } if (!mTouchable) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; } if (mOutsideTouchable) { curFlags |= WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; } if (!mClippingEnabled || mClipToScreen) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; } if (isSplitTouchEnabled()) { curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; } if (mLayoutInScreen) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; } if (mLayoutInsetDecor) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; } if (mNotTouchModal) { curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; } if (mAttachedInDecor) { curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR; } return curFlags; }
根据PopWindow的创建过程,及createPopupLayoutParams中可以确认有个flags,这个里面的flags作用是什么,看上面computeFlags函数源码:首先会先把这几种状态清除,再根据变量去设置,其中有一个WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL:获取焦点的情况下,设置这个属性可以把Window之外的event发送到window后面其他的window上,因此我们可以设置它为true,把窗口外的event传递,根据:
/** * Set whether this window is touch modal or if outside touches will be sent to * other windows behind it. * @hide */ public void setTouchModal(boolean touchModal) { mNotTouchModal = !touchModal; }
可以看出,直接调用不可使用为hide,mNotTouchModal = !touchModal;所以外部设置false即可,可使用反射的办法去解决:
try { Method method = PopupWindow.class.getDeclaredMethod("setTouchModal", boolean.class); method.setAccessible(true); method.invoke(popupWindow, false); } catch (Exception e) { e.printStackTrace(); }
经测试,6.0系统之后点击PopWindow的外部可以实现窗口不消失。
0 0
- PopupWindow 系统6.0以上 setOutsideTouchable失效分析
- PopupWindow setOutsideTouchable 问题
- fragment中中设置PopupWindow setOutsideTouchable无效的问题
- PopupWindow setOutsideTouchable(false)无效问题完美解决方案
- Popupwindow在Android 7.0以上系统位置显示不对的解决办法
- PopupWindow分析
- 关于popupWindow设置了setBackgroundDrawable和setOutsideTouchable任然不能点击外部或者后退键不能返回
- iOS开发--iOS7以上自定义leftBarButtonItem后系统滑动返回失效的完美解决方案
- windows x64 vista以上系统代码完整性校验分析
- 从源码剖析PopupWindow 兼容Android 6.0以上版本点击外部不消失
- Android 6.0以上系统webview的bug
- [Android] 6.0以上系统动态权限说明
- Android 6.0以上系统动态获取权限
- PopupWindow 滑动时背景失效bug
- PopUpWindow 位置分析
- PopupWindow源码分析
- PopupWindow源码分析
- PopupWindow源码分析
- android 百度语音识别(离在线)以及唤醒功能
- c#学习之??和?分别代表的意思
- GIF 格式图片的存储和压缩 Node.js实现
- java 集合类
- STM32的CAN波特率计算
- PopupWindow 系统6.0以上 setOutsideTouchable失效分析
- Frangment嵌套出现重叠的情况
- Mapreduce 整个工作机制图
- ~ 使用redis缓存数据需要注意的问题以及个人的一些思考和理解
- jquery清空元素内容
- PHP判断是否为移动端访问
- 关于Hibernate一级缓存的快照问题
- 给初学者的RxJava2.0教程(五)
- 数据库并发控制