Android API 35+下Java实现状态栏/导航栏颜色与高度的问题求助
Android API 35+ 状态栏/导航栏适配实现代码
以下是针对API 35+优化的Java工具类,包含系统栏背景色设置、高度获取及刘海区域参数获取逻辑,适配最新API废弃规则:
import android.app.Activity; import android.graphics.Color; import android.graphics.Rect; import android.os.Build; import android.view.DisplayCutout; import android.view.View; import android.view.Window; import android.view.WindowInsets; import android.view.WindowInsetsController; import java.util.List; public class AndroidSystemBarUtils { // 设置状态栏与导航栏背景色,自动适配文字图标深浅 public static void setSystemBarsColor(Activity activity, int statusBarColor, int navBarColor) { Window window = activity.getWindow(); // 让布局延伸至系统栏下方,确保背景色生效 window.setDecorFitsSystemWindows(false); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsetsController insetsController = window.getInsetsController(); if (insetsController == null) return; window.setStatusBarColor(statusBarColor); window.setNavigationBarColor(navBarColor); // 根据背景色自动切换状态栏文字图标深浅 boolean isStatusBarDark = isColorDark(statusBarColor); insetsController.setSystemBarsAppearance( isStatusBarDark ? WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS : 0, WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS ); // 根据背景色自动切换导航栏图标深浅 boolean isNavBarDark = isColorDark(navBarColor); insetsController.setSystemBarsAppearance( isNavBarDark ? WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS : 0, WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS ); } } // 获取状态栏高度(需在View附着窗口后调用) public static int getStatusBarHeight(Activity activity) { int height = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); if (insets != null) { height = insets.getInsets(WindowInsets.Type.statusBars()).top; } } else { // 兼容旧版本,可按需保留 int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resId > 0) height = activity.getResources().getDimensionPixelSize(resId); } return height; } // 获取导航栏高度(需在View附着窗口后调用) public static int getNavigationBarHeight(Activity activity) { int height = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); if (insets != null) { height = insets.getInsets(WindowInsets.Type.navigationBars()).bottom; } } else { // 兼容旧版本,可按需保留 int resId = activity.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resId > 0) height = activity.getResources().getDimensionPixelSize(resId); } return height; } // 获取刘海区域所有裁剪矩形 public static List<Rect> getDisplayCutoutAreas(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); if (insets != null) { DisplayCutout cutout = insets.getDisplayCutout(); if (cutout != null) return cutout.getBoundingRects(); } } return null; } // 获取刘海顶部安全边距(状态栏额外高度) public static int getDisplayCutoutTopInset(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets(); if (insets != null) { DisplayCutout cutout = insets.getDisplayCutout(); if (cutout != null) return cutout.getSafeInsetTop(); } } return 0; } // 判断颜色是否为深色,用于切换系统栏文字图标颜色 private static boolean isColorDark(int color) { double darkness = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; return darkness >= 0.5; } }
核心注意事项
- 调用高度、刘海参数方法时,必须确保View已附着到窗口(比如在Activity的
onWindowFocusChanged(boolean hasFocus)中调用,或给View添加OnAttachStateChangeListener监听),否则WindowInsets会返回null,导致高度为0。 - 必须执行
window.setDecorFitsSystemWindows(false),否则布局无法延伸至系统栏,Insets获取会异常。 - QT开发者可将此类打包为Android库,或直接在QT对应的Android入口类中实现,通过JNI调用对应方法。
内容的提问来源于stack exchange,提问作者Jiri Zaloudek
相关产品推荐
相关产品推荐

