前段时间遇到一个问题,需要在一个popupWindow里计算当前状态栏的高度,百度了下相关的方法,要么是直接读取系统里状态栏高度的值,但是无法判断状态栏是否显示,要么就需要在一个activity里通过getWindow获取window对象来判断,有局限性。自己鼓捣了半天,外加百度来的一些信息,想出一个可以同时判断状态栏是否显示以及获取状态栏高度的方法,还不依赖于activity。
为了方便自己对比和记忆,先总结几种常见的方法
- 直接读取系统里状态栏高度的值,方便快捷,但是缺点就是无法判断当前状态栏是否显示
// 直接读取系统里状态栏高度的值,但是无法判断状态栏是否显示
private void getStatusBarHeight(){
int height = 0;
//获取status_bar_height资源的ID
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
//根据资源ID获取响应的尺寸值
height = getResources().getDimensionPixelSize(resourceId);
}
Log.d(TAG,height+"");
}
2. 判断当前window的flag是否是full_screen,缺点是无法获得状态栏的高度和只能在activity中使用
private void isStatusBarVisible(){
if ((getWindow().getAttributes().flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0){
Log.d(TAG,"status bar is visible");
} else {
Log.d(TAG,"status bar is not visible");
}
}
3. 像这样的需求,必须判断状态栏是否显示,同时必须获得状态栏的高度,而且能在任意地方使用,不局限于acivity,就必须用到另外一个方法了,如下
package com.justwen.demo.statusbar;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.WindowManager;
public class StatusBarService extends Service {
private static final String TAG = "statusbar";
private View mStatusBarHelperView;
private class StatusBaroController extends Binder {
public int getStatusBarHeight(){
return StatusBarService.this.getStatusBarHeight();
}
}
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);
}
private void removeStatusBarHelperView(){
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
wm.removeView(mStatusBarHelperView);
mStatusBarHelperView = null;
}
private int getStatusBarHeight(){
int[] screenParams = new int[2];
mStatusBarHelperView.getLocationOnScreen(screenParams);
// 如果状态栏隐藏,返回0,如果状态栏显示则返回高度
return screenParams[1];
}
@Override
public IBinder onBind(Intent intent) {
return new StatusBaroController();
}
@Override
public void onCreate() {
super.onCreate();
initStatusBarHelperView();
}
@Override
public void onDestroy() {
super.onDestroy();
removeStatusBarHelperView();
}
}
原理是使用WindowManager在窗口左上角添加一个透明的View,然后获取这个View在整个屏幕上的位置screenParams,如果状态栏隐藏,那么screenParams[1]应为0, 如果状态栏是显示的,那么screenParams[1]就是状态栏的高度。
注意 :
- screenParams和windowParams不能在wm.addView之后马上获取,不然会得到0。
- 如果不使用后记得调用wm.removeView。
- 需要在androidManifest添加浮动窗口权限,如果是M以上的手机,还必须获取动态权限。
private void requestAlertWindowPermission() { Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 1); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 1) { if (Settings.canDrawOverlays(this)) { Log.i(TAG, "onActivityResult granted"); startService(new Intent(this,StatusBarService.class)); } } }