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

Flutter中实现亮色/暗色/系统主题切换

Flutter中实现亮色/暗色/系统主题切换

嘿,看起来你已经搭好了主题切换的基础架子!要实现亮色、暗色和跟随系统这三个选项,咱们得调整下现有代码,让它既能记住用户的选择,又能跟着系统主题变化自动更新。下面一步步来完善:

第一步:升级你的ThemeChanger Provider

原来的ThemeChanger只存了固定的ThemeData,没法应对系统主题变化和用户的不同选择。咱们改成记录用户的主题模式偏好,再根据这个偏好动态生成对应的主题:

import 'package:flutter/material.dart';

// 直接用Flutter自带的ThemeMode来表示主题偏好选项就够用啦
enum ThemePreference { light, dark, system }

class ThemeChanger with ChangeNotifier {
  // 记录用户选择的主题偏好
  ThemePreference _preference = ThemePreference.system;
  // 缓存系统当前的主题模式
  ThemeMode _systemThemeMode = ThemeMode.light;

  ThemeChanger() {
    // 初始化时获取系统当前主题,并监听后续变化
    _initSystemThemeListener();
  }

  // 给外部提供当前偏好的getter
  ThemePreference get preference => _preference;

  // 获取当前应该使用的主题模式
  ThemeMode get currentThemeMode {
    switch (_preference) {
      case ThemePreference.light:
        return ThemeMode.light;
      case ThemePreference.dark:
        return ThemeMode.dark;
      case ThemePreference.system:
        return _systemThemeMode;
    }
  }

  // 获取对应的ThemeData(这里可以替换成你自定义的亮色/暗色主题)
  ThemeData get currentTheme {
    switch (currentThemeMode) {
      case ThemeMode.light:
        return ThemeData.light(useMaterial3: true);
      case ThemeMode.dark:
        return ThemeData.dark(useMaterial3: true);
      default:
        return ThemeData.light(useMaterial3: true);
    }
  }

  // 设置用户的主题偏好
  void setThemePreference(ThemePreference newPreference) {
    _preference = newPreference;
    notifyListeners();
  }

  // 监听系统主题变化的方法
  void _initSystemThemeListener() {
    final window = WidgetsBinding.instance.window;
    // 初始化系统当前主题
    _updateSystemTheme(window.platformBrightness);
    // 监听系统主题变更
    window.onPlatformBrightnessChanged = () {
      _updateSystemTheme(window.platformBrightness);
      notifyListeners();
    };
  }

  void _updateSystemTheme(Brightness brightness) {
    _systemThemeMode = brightness == Brightness.dark ? ThemeMode.dark : ThemeMode.light;
  }
}

第二步:在main.dart中配置Provider

要让整个App都能访问到ThemeChanger,得把它放到顶层的Provider里:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'home.dart';
import 'theme_changer.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => ThemeChanger(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeChanger>(
      builder: (context, themeChanger, child) {
        return MaterialApp(
          title: '主题切换Demo',
          theme: themeChanger.currentTheme,
          home: const HomePage(),
        );
      },
    );
  }
}

第三步:在HomePage中添加主题切换UI

现在咱们给HomePage加个切换选项,比如用下拉菜单让用户直观选择:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'theme_changer.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final themeChanger = Provider.of<ThemeChanger>(context);
    return Scaffold(
      appBar: AppBar(
        title: const Text('AppBar'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('选择主题模式:'),
            const SizedBox(height: 16),
            DropdownButton<ThemePreference>(
              value: themeChanger.preference,
              items: const [
                DropdownMenuItem(
                  value: ThemePreference.light,
                  child: Text('亮色主题'),
                ),
                DropdownMenuItem(
                  value: ThemePreference.dark,
                  child: Text('暗色主题'),
                ),
                DropdownMenuItem(
                  value: ThemePreference.system,
                  child: Text('跟随系统'),
                ),
              ],
              onChanged: (value) {
                if (value != null) {
                  themeChanger.setThemePreference(value);
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}

小提醒

  • 如果你有自己定制的亮色/暗色主题,直接替换currentTheme里的ThemeData.light()和ThemeData.dark()就行。
  • 这样改造后,用户选择「跟随系统」时,App会自动同步手机的系统主题变化,另外两个选项则会固定使用对应模式。

备注:内容来源于stack exchange,提问作者ira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.17 10:39:38