You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何让setSystemUIOverlayStyle颜色随主题模式动态变化?

解决SystemUiOverlayStyle随系统主题切换不生效的问题

问题原因

你当前的代码仅在Widget重建(比如页面导航)时执行SystemChrome.setSystemUIOverlayStyle,但系统主题切换时,当前页面的Widget不会自动触发build,导致样式没有同步更新。

解决方案

方案1:通过WidgetsBindingObserver监听主题变化

让页面的State类混入WidgetsBindingObserver,监听系统亮度变化事件,实时更新UI样式:

class _YourPageState extends State<YourPage> with WidgetsBindingObserver {
  // 简化深色模式判断逻辑
  bool isDarkModeOn(BuildContext context) => 
      Theme.of(context).brightness == Brightness.dark;

  void _updateSystemUiStyle() {
    final systemThemeLight = SystemUiOverlayStyle.light.copyWith(
      systemNavigationBarColor: const Color(0xdfd6f5ca),
      systemNavigationBarIconBrightness: Brightness.light,
    );
    final systemThemeDark = SystemUiOverlayStyle.dark.copyWith(
      systemNavigationBarColor: Colors.black,
      systemNavigationBarIconBrightness: Brightness.light,
    );
    SystemChrome.setSystemUIOverlayStyle(
      isDarkModeOn(context) ? systemThemeDark : systemThemeLight
    );
  }

  @override
  void initState() {
    super.initState();
    // 注册系统事件监听
    WidgetsBinding.instance.addObserver(this);
    // 初始化时设置一次样式
    _updateSystemUiStyle();
  }

  @override
  void didChangePlatformBrightness() {
    super.didChangePlatformBrightness();
    // 系统亮度变化时触发样式更新
    _updateSystemUiStyle();
  }

  @override
  void dispose() {
    // 页面销毁时取消监听
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // 你的页面布局代码
    return Scaffold(body: ...);
  }
}

方案2:用AnimatedBuilder监听Theme变化

借助AnimatedBuilder监听Theme.of(context)的变化,自动触发样式更新:

@override
Widget build(BuildContext context) {
  return AnimatedBuilder(
    animation: Theme.of(context),
    builder: (context, child) {
      final systemThemeLight = SystemUiOverlayStyle.light.copyWith(
        systemNavigationBarColor: const Color(0xdfd6f5ca),
        systemNavigationBarIconBrightness: Brightness.light,
      );
      final systemThemeDark = SystemUiOverlayStyle.dark.copyWith(
        systemNavigationBarColor: Colors.black,
        systemNavigationBarIconBrightness: Brightness.light,
      );
      SystemChrome.setSystemUIOverlayStyle(
        Theme.of(context).brightness == Brightness.dark 
            ? systemThemeDark 
            : systemThemeLight
      );
      return child!;
    },
    child: Scaffold(
      // 你的页面布局内容
    ),
  );
}

方案3:依赖MediaQuery触发build

让build方法依赖MediaQuery.of(context).platformBrightness,系统主题变化时会自动触发build更新样式:

@override
Widget build(BuildContext context) {
  // 依赖系统亮度值,确保主题变化时触发build
  final isDark = MediaQuery.of(context).platformBrightness == Brightness.dark;
  
  final systemThemeLight = SystemUiOverlayStyle.light.copyWith(
    systemNavigationBarColor: const Color(0xdfd6f5ca),
    systemNavigationBarIconBrightness: Brightness.light,
  );
  final systemThemeDark = SystemUiOverlayStyle.dark.copyWith(
    systemNavigationBarColor: Colors.black,
    systemNavigationBarIconBrightness: Brightness.light,
  );
  SystemChrome.setSystemUIOverlayStyle(isDark ? systemThemeDark : systemThemeLight);

  return Scaffold(body: ...);
}

注意事项

  • 方案1是最直接的系统事件监听方式,适合单页面或全局的样式同步需求;
  • 方案2、3通过Widget重建触发更新,需确保当前Widget会因主题变化而重建;
  • 如果是全局主题切换场景,也可以在MaterialApp的builder方法中统一处理系统UI样式。

内容的提问来源于stack exchange,提问作者Fabian M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:01:38