Flutter 设置Android System Navigation/Status Bar背景色

背景

公司要求必须使用Edge-to-Edge不允许使用Android中的theme.xml或style.xml资源文件来通过android:navigationBarColor或android:statusBarColor属性进行对自定义系统Bar的背景进行改色,更不用提android.view.Window.setStatusBarColor 和 android.view.Window.setNavigationBarColor方法了
如何设置背景色?在哪里设置?为什么在这里设置?我们带着这三个问题,来对这篇文章进行阅读。

如何设置背景色?

直接上代码

dart 复制代码
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);

SystemChrome.setSystemUIOverlayStyle(
    SystemUiOverlayStyle(
        systemNavigationBarContrastEnforced: false,
        systemNavigationBarIconBrightness: Brightness.dark, // 图标颜色-> dark深色;light亮色
        systemNavigationBarColor: Colors.white, // 设置导航栏(条)背景颜色
        statusBarColor: Colors.white, // 设置状态栏背景颜色
    ),
);

关键点:

  • 开启Edge-to-Edge沉浸模式

  • systemNavigationBarContrastEnforced 设置为 false,这个参数在部分Android系统中(特别是MIUI)中是控制颜色"反转"或"强制对比"的关键,设置成false能确保你指定的颜色不被系统覆盖

在哪里设置?

  1. 使用了MaterialApp组件作为App入口,那么要在builder返回值之前进行设置:
dart 复制代码
void main() {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(ProviderScope(child: const MyApp()));
}

class MyApp extends StatelessWidget {

    const MyApp({super.key});

    @override
    Widget build(BuildContext context) {
        return MaterailApp(

        builder: (context,child){
            // 在此设置
            SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
            SystemChrome.setSystemUIOverlayStyle(
                SystemUiOverlayStyle(
                    systemNavigationBarContrastEnforced: false,
                    systemNavigationBarIconBrightness: Brightness.dark,
                    systemNavigationBarColor: Colors.white,
                    statusBarColor: Colors.white,
                ),
            );
            return child!;
        });
    }
}
  1. 没有使用MaterialApp组件作为App入口,那么要在runApp()方法之前执行设置即可:
dart 复制代码
void main() {
    WidgetsFlutterBinding.ensureInitialized();

    // 在此设置
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setSystemUIOverlayStyle(
        SystemUiOverlayStyle(
            systemNavigationBarContrastEnforced: false,
            systemNavigationBarIconBrightness: Brightness.dark,
            systemNavigationBarColor: Colors.white,
            statusBarColor: Colors.white,
        )
    );
    runApp(ProviderScope(child: const MyApp()));
}

为什么在这里设置?

重点 :MaterialApp组件中,无论你设置设置怎样的主题样式,都在组件内部调用一次SystemChrome.setSystemUIOverlayStyle函数,这会让你在MaterialApp组件绘制之前设置的SystemBar背景颜色均被MaterialApp的这一次函数调用覆盖。我们来看下源码

dart 复制代码
class MaterialApp extends StatefulWidget {
    ...
    @override
    State<MaterialApp> createState() => _MaterialAppState();
    ...
}

class _MaterialAppState extends State<MaterialApp> {

    @override
    Widget build(BuildContext context) {
        Widget result = _buildWidgetApp(context);
        ...
        return ScrollConfiguration(
            behavior: widget.scrollBehavior ?? const MaterialScrollBehavior(),
            child: HeroControllerScope(controller: _heroController, child: result),
        );
    }

    Widget _buildWidgetApp(BuildContext context) {
        final Color materialColor = widget.color ?? widget.theme?.primaryColor ?? Colors.blue;
        if (_usesRouter) {
            return WidgetsApp.router(
                ...,
                builder: _materialBuilder, // 重点位置
                ...,
            );
        }

        return WidgetsApp(
            ...,
            builder: _materialBuilder, // 重点位置
            ...,
        );
    }

    Widget _materialBuilder(BuildContext context, Widget? child) {
        final ThemeData theme = _themeBuilder(context); // 重点位置
        final Color effectiveSelectionColor =
        theme.textSelectionTheme.selectionColor ?? theme.colorScheme.primary.withOpacity(0.40);
        final Color effectiveCursorColor =
        theme.textSelectionTheme.cursorColor ?? theme.colorScheme.primary;
        Widget childWidget = child ?? const SizedBox.shrink();
        
        // 重点位置
        if (widget.builder != null) {
            childWidget = Builder(
                builder: (BuildContext context) {
                    return widget.builder!(context, child);
                },
            );
        }
        ...
    }

    ThemeData _themeBuilder(BuildContext context) {
        ThemeData? theme;
        ...
        if (useDarkTheme && highContrast && widget.highContrastDarkTheme != null) {
            theme = widget.highContrastDarkTheme;
        } else if (useDarkTheme && widget.darkTheme != null) {
            theme = widget.darkTheme;
        } else if (highContrast && widget.highContrastTheme != null) {
            theme = widget.highContrastTheme;
        }
        theme ??= widget.theme ?? ThemeData();
        // 此处的brightness 是 colorScheme.brightness 无论你设置与否都会将SystemBar 设置成light or dark
        SystemChrome.setSystemUIOverlayStyle(
            theme.brightness == Brightness.dark ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark,
        ); // 重点位置
        
        return theme;
    }

}
相关推荐
朱涛的自习室7 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
程序员老刘12 小时前
跨平台开发地图 | 2026年10月
flutter·ai编程·客户端
应用市场13 小时前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
一铭1119914 小时前
海豹办公 1.9.15 跨端办公软件实践 文档兼容 Access 数据库与移动 WebView 排错
android·数据库·electron·开源软件·access
林瞅瞅14 小时前
Flutter 开发环境从零搭建与调试记录
flutter
geats人山人海14 小时前
java 7异常
android·java·开发语言
2601_9620710015 小时前
Kimi K3 vs DeepSeek V4-Pro实测对比:2026年同一入口十道题,耗时与token消耗差在哪
android·java·数据库
右手吉他16 小时前
高通平台IA APN问题分析之二
android·物联网
夜雪一千17 小时前
MySQL 自增 ID 的底层原理与坑点
android·mysql·adb
不浪费一个字节17 小时前
一个纯 Python 实现的 APK 解析与设备操控工具箱
android