- 前言
由于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.
* <p>
* 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.
* <p>
* Requires {@link android.Manifest.permission#SYSTEM_ALERT_WINDOW} permission.
* <p>
* The system will adjust the importance of processes with this window type to reduce the
* chance of the low-memory-killer killing them.
* <p>
* 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;
}