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
    }

 

posted @ 2022-11-07 16:58  随易来了  阅读(95)  评论(0编辑  收藏  举报