Android 全屏悬浮窗适配(悬浮窗沉浸式)

  • 前言
    由于Android 高版本的类型限制,如果我们使用WindowsManager 做悬浮窗,会被限制在当前窗口内容中。而当前窗口大小会限制在状态栏和导航栏之间,所以会导致悬浮窗沉浸不了状态栏。

高版本windowsmanager 限制 源码


        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//6.0+
            mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;

        } else {
            mParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
        }

        /**
         * Window type: Application overlay windows are displayed above all activity windows
         * (types between {@link #FIRST_APPLICATION_WINDOW} and {@link #LAST_APPLICATION_WINDOW})
         * but below critical system windows like the status bar or IME.
         * 

* The system may change the position, size, or visibility of these windows at anytime * to reduce visual clutter to the user and also manage resources. *

* Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission. *

* The system will adjust the importance of processes with this window type to reduce the * chance of the low-memory-killer killing them. *

* In multi-user systems shows only on the owning user's screen. */ public static final int TYPE_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 38;

上面注解简单描述的意思就是:

应用程序覆盖窗口显示在所有活动窗口之上 ,但是级别会低于状态栏和IME,所以,从这里我们可以看出,当我们使用type=TYPE_APPLICATION_OVERLAY, 是很难将窗口沉浸到状态栏上的。

那要怎么做呢?

高版本WindowManager 沉浸状态栏

创建WindowManager 和LayoutParams

 WindowManager  wManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
 WindowManager.LayoutParams mParams = new WindowManager.LayoutParams();

设置Params 参数

        mParams.format = PixelFormat.TRANSLUCENT;// 支持透明
        //mParams.format = PixelFormat.RGBA_8888;l
//        mParams.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;// 焦点

        mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                // 加上这句话悬浮窗不拦截事件
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                | WindowManager.LayoutParams.FLAG_FULLSCREEN
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;

注意看,这里有一句核心,WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
意思是,不受边界影响,可以超出窗口边界!!!

加载布局,设置布局沉浸~

        View  inflate = LayoutInflater.from(this).inflate(R.layout.view_widow_layout, null);

        ImageView   imageView = inflate.findViewById(R.id.iv);
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);

        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
        layoutParams.topMargin=-StatusBarUtils.getStatusBarHeight(this);
        imageView.setLayoutParams(layoutParams);

       wManager.addView(inflate, mParams);//添加窗口

核心: layoutParams.topMargin=-StatusBarUtils.getStatusBarHeight(this);
通过获取状态栏高度,设置布局的margin为负数达到超出边界刚好为状态栏的高度,从而达到沉浸式效果!!

最后附上获取状态栏高度

    /**
     * 获取状态栏高度
     * @param context
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        Resources resources = context.getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }

你可能感兴趣的:(java,android)