最近在做一个要在任何位置获取SystemUI状态栏是否隐藏的需求方案,经过百度查找,诸多同行们无非是采用以下两种方法:
1.根据Android系统尺寸资源中status_bar_height获取当前状态栏的高度是否为0来判断状态栏是否隐藏;
2.根据getWindow().getDecorView().getWindowVisibleDisplayFrame(outRect1)方法获取。
以上两个方案虽然都能够判断但是都具有一定的局限性,第一种能够获取到高度但是当状态栏隐藏的时候获取的高度没有变化;第二种倒是能够满足实时获取状态栏高度来达到判断状态栏是否隐藏的目的,但是该方法只能够应用于Activity等显示性的View中。因此,都不满足在Service服务中判断状态栏是否隐藏的目的。
后来发现另外一种自定义View,通过判断该View在屏幕上X、Y的坐标进而来达到状态栏是否隐藏的目的,相关核心方法如下:
//初始化自定义View private void initStatusBarHelperView() { WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); mStatusBarHelperView = new View(this); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); // 不可触摸,不可获得焦点 lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; // 放在左上角 lp.gravity = Gravity.LEFT | Gravity.TOP; // 需要在manifest里申明android.permission.SYSTEM_ALERT_WINDOW权限 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; lp.format = PixelFormat.TRANSLUCENT; wm.addView(mStatusBarHelperView, lp); } //使用完毕移除自定义View private void removeStatusBarHelperView() { WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); wm.removeView(mStatusBarHelperView); mStatusBarHelperView = null; } /** * * @return true 状态栏隐藏;false状态栏显示 */ private boolean getStatusBarHeight() { int[] windowParams = new int[2]; int[] screenParams = new int[2]; mStatusBarHelperView.getLocationInWindow(windowParams); mStatusBarHelperView.getLocationOnScreen(screenParams); // 如果状态栏隐藏,返回0,如果状态栏显示则返回高度 Logger.d("zqh", "getStatusBarHeight = "+(screenParams[1] - windowParams[1])); return (screenParams[1] - windowParams[1])==0; } /** * * @return true 状态栏隐藏;false状态栏显示 */ private boolean getStatusBarHeight2(){ int[] screenParams = new int[2]; mStatusBarHelperView.getLocationOnScreen(screenParams); return screenParams[0]==0 && screenParams[1]==0; }
以上方法的原理就是使用WindowManager在窗口的左上角添加一个透明的View,并设置该View为不可触摸,然后获取这个View在整个屏幕上的位置screenParams和在其父控件(应用区域)窗口上的位置windowParams,若是状态栏隐藏,则两者的纵坐标的数值是一样的,两者相差为0;若是状态栏是显示的,则两者的差值就是状态栏的高度。此外,也可以根据若是状态栏隐藏则View在整个屏幕上的位置screenParams的X、Y坐标值都为0,也可进行判断。注意要是采取:screenParams和windowParams则不能在wm.addView()之后马上获取,否则会取到0,在使用完毕之后一定要wm.removeView();