【Android】获取导航栏、状态栏高度

获取状态栏高度

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更新背景色的方法,还有如下位置:
【Android】获取导航栏、状态栏高度_第1张图片

#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

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);
;
});

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