Andoird Window 简单使用
1、windowmanager 获取系统服务对象
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
2、设置需要显示window的参数
重要参数类型作用:
1、params.flags 参考:WindowManager.LayoutParams全解 - 一点点征服 - 博客园 (cnblogs.com)
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE //不能获取输入焦点
- WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE //不接受触摸事件
- WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL //可获得焦点和事件。即使在该window在可获得焦点情况下,仍然把该window之外的任何event发送到该window之后的其他window.
- WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH //如果你设置了该flag,那么在你FLAG_NOT_TOUNCH_MODAL的情况下,即使触摸屏事件发送在该window之外,其事件被发送到了后面的window,那么该window仍然将以MotionEvent.ACTION_OUTSIDE形式收到该触摸屏事件
2、params.format = PixelFormat.RGBA_8888;//设置窗口背景色透明
3、params.type :控制系统窗口层级 参考:WindowManager.LayoutParams.type属性 - 熠然 - 博客园 (cnblogs.com)
Type表示Window的类型,一共三种:
应用Window
。对应着一个Activity,Window层级为1~99,在视图最下层。子Window
。不能单独存在,需要附属在特定的父Window之中(如Dialog就是子Window),Window层级为1000~1999。系统Window
。需要声明权限才能创建的Window,比如Toast和系统状态栏,Window层级为2000-2999,处在视图最上层。
可以看到,区别就是有个Window层级(z-ordered),层级高的能覆盖住层级低的,离用户更近。
public static WindowManager.LayoutParams getParams(Context context) { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; params.height =(int) context.getResources().getDimension(R.dimen.dp_992); params.width = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSPARENT; params.gravity = Gravity.START | Gravity.TOP; params.y = (int) context.getResources().getDimension(R.dimen.dp_88); XCCommonUtils.LOGD(TAG, " params.x=" + params.x + "params.y=" + params.y); try { if (policy != null) { params.type = policy.getWindowManagerPolicy().getWindowTypeByCode(IWindowManagerPolicy.CODE_INTELLIGENT_AVATAR); XCCommonUtils.LOGD(TAG, "params.type=" +params.type); } } catch (Exception e) { e.printStackTrace(); } return params; }
3、添加window到屏幕
mWindowManager.addView(mView, mLayoutParams);
4、点击window区域外dismiss Window
@Override public void setView(View view) { mView = view; mView.getRootView().setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Lg.e("onTouch", "MotionEvent:" + event); if (MotionEvent.ACTION_OUTSIDE == event.getAction()) { dismiss(); } return false; } }); } @Override public void dismiss() { mWindowManager.removeView(mView); }
如果没有监听到ACTION_OUTSIDE事件:
(1)检查根View的layout文件宽高是否设置为wrap,或者通过prams.width、prams.height设置具体的数值
(2)在onTouchEvent事件里监听窗口事件。view.setTouchListener为view的事件
另外,也可以通过点击屏幕的坐标与view在屏幕的坐标范围,综合判断是否为点击window显示区域外事件
private fun outsideOfWindow(event: MotionEvent): Boolean { LogUtils.d(TAG, "MotionEvent $event") return event.x < 0 || event.x > WindowUtils.WINDOW_WIDTH || event.y < 0 || event.y > WindowUtils.WINDOW_HEIGHT }