public static int getStatusBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
或者
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
int statuBarHeight = insets.getStableInsetTop();
return insets;
});
public static int getNavigationBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
或者
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
int navigationBarHeight = insets.getStableInsetBottom();
return insets;
});
系统的各种数据定义位于SDK的xml文件中:
android-30/data/res/values/dimens.xml
<dimen name="toast_y_offset">24dpdimen>
<dimen name="status_bar_height">@dimen/status_bar_height_portraitdimen>
<dimen name="status_bar_height_portrait">24dpdimen>
<dimen name="status_bar_height_landscape">@dimen/status_bar_height_portraitdimen>
<dimen name="navigation_bar_height">48dpdimen>
<dimen name="navigation_bar_height_landscape">48dpdimen>
<dimen name="navigation_bar_width">48dpdimen>
通过key可以获取对应的值。
getWindow().setStatusBarColor(Color.RED);
getWindow().setNavigationBarColor(Color.RED);
导航栏和状态栏源码相似
#PhoneWindow
@Override
public void setStatusBarColor(int color) {
mStatusBarColor = color;
mForcedStatusBarColor = true;
if (mDecor != null) {
mDecor.updateColorViews(null, false /* animate */);
}
}
#DecorView
public static final ColorViewAttributes STATUS_BAR_COLOR_VIEW_ATTRIBUTES =
new ColorViewAttributes(SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
Gravity.TOP, Gravity.LEFT, Gravity.RIGHT,
Window.STATUS_BAR_BACKGROUND_TRANSITION_NAME,
com.android.internal.R.id.statusBarBackground,
FLAG_FULLSCREEN, ITYPE_STATUS_BAR);
public static final ColorViewAttributes NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES =
new ColorViewAttributes(
SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
Gravity.BOTTOM, Gravity.RIGHT, Gravity.LEFT,
Window.NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
com.android.internal.R.id.navigationBarBackground,
0 , ITYPE_NAVIGATION_BAR);
private final ColorViewState mStatusColorViewState = new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
private final ColorViewState mNavigationColorViewState = new ColorViewState(NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES);
WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
...
updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
0 /* sideInset */, animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, controller);
...
updateColorViewInt(mStatusColorViewState, sysUiVisibility,
calculateStatusBarColor(), 0, mLastTopInset,
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, controller);
}
调用updateColorViews
更新背景色的方法,还有如下位置:
#ViewRootImpl
private void performTraversals() {
dispatchApplyInsets(host);
}
public void dispatchApplyInsets(View host) {
mApplyInsetsRequested = false;
WindowInsets insets = getWindowInsets(true /* forceConstruct */);
host.dispatchApplyWindowInsets(insets);
...
}
#View
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
...
return onApplyWindowInsets(insets);
...
}
#DecorView
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
...
insets = updateColorViews(insets, true);
...
return insets;
}
WindowInsets
可以翻译为窗口附加物,一般是指一个界面中,不由开发者直接控制的部分,例如:状态栏、底部的导航栏等等。具体的类型在Type中有定义:
#WindowInsets.Type
static final int FIRST = 1 << 0;
static final int STATUS_BARS = FIRST;
static final int NAVIGATION_BARS = 1 << 1;
static final int CAPTION_BAR = 1 << 2;
static final int IME = 1 << 3;
static final int SYSTEM_GESTURES = 1 << 4;
static final int MANDATORY_SYSTEM_GESTURES = 1 << 5;
static final int TAPPABLE_ELEMENT = 1 << 6;
static final int DISPLAY_CUTOUT = 1 << 7;
static final int LAST = 1 << 8;
static final int SIZE = 9;
static final int WINDOW_DECOR = LAST;
可以向DecorView
添加监听,处理WindowInsets
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
return insets;
});
所以,可以在这里获取导航栏和状态栏的高度:
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
int statuBarHeight = insets.getStableInsetTop();
int navigationBarHeight = insets.getStableInsetBottom();
return insets;
});
也可以修改导航栏和状态栏的高度(好像没有应用场景):
getWindow().getDecorView().setOnApplyWindowInsetsListener((v, insets) -> {
int statuBarHeight = 0;
int navigationBarHeight = 0;
return insets.replaceSystemWindowInsets(0,statuBarHeight,0,navigationBarHeight);
;
});