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

Flutter中根据主题切换全局颜色的实现方法

实现主题切换下的动态颜色配置

1. 重构颜色类,支持双主题配置

把原有的静态常量拆分成浅色、深色两套配置,通过主题模式返回对应颜色:

class ThemeColors {
  // 浅色主题颜色集
  static const _light = {
    'primary': Color.fromRGBO(25, 155, 241, 1),
    'secondaryFont': Color.fromRGBO(100, 100, 100, 1),
    'primaryFont': Colors.black,
    'background': Color.fromRGBO(245, 245, 245, 1),
    'successToast': Color.fromRGBO(218, 255, 226, 1),
    'warningToast': Color.fromRGBO(255, 236, 199, 1),
    'errorToast': Color.fromRGBO(255, 157, 136, 1),
    'noticeBadWeather': Color.fromRGBO(41, 41, 41, 1),
    'noticeUrgent': Color.fromRGBO(199, 31, 46, 1),
    'noticeImportant': Color.fromRGBO(252, 192, 78, 1),
    'noticeRegular': Color.fromRGBO(115, 161, 184, 1),
    // 其他浅色颜色
  };

  // 深色主题颜色集
  static const _dark = {
    'primary': Color.fromRGBO(30, 160, 250, 1),
    'secondaryFont': Color.fromRGBO(180, 180, 180, 1),
    'primaryFont': Colors.white,
    'background': Color.fromRGBO(30, 30, 30, 1),
    'successToast': Color.fromRGBO(60, 200, 80, 1),
    'warningToast': Color.fromRGBO(255, 200, 120, 1),
    'errorToast': Color.fromRGBO(255, 120, 100, 1),
    'noticeBadWeather': Color.fromRGBO(200, 200, 200, 1),
    'noticeUrgent': Color.fromRGBO(255, 60, 70, 1),
    'noticeImportant': Color.fromRGBO(255, 220, 100, 1),
    'noticeRegular': Color.fromRGBO(140, 180, 200, 1),
    // 其他深色颜色
  };

  // 根据主题模式获取对应颜色
  static Color _get(String key, ThemeMode mode) {
    return mode == ThemeMode.light ? _light[key] ?? Colors.transparent : _dark[key] ?? Colors.transparent;
  }

  // 封装成直观的属性方法,方便调用
  static Color primary(ThemeMode mode) => _get('primary', mode);
  static Color secondaryFont(ThemeMode mode) => _get('secondaryFont', mode);
  static Color primaryFont(ThemeMode mode) => _get('primaryFont', mode);
  static Color background(ThemeMode mode) => _get('background', mode);
  static Color successToast(ThemeMode mode) => _get('successToast', mode);
  static Color warningToast(ThemeMode mode) => _get('warningToast', mode);
  static Color errorToast(ThemeMode mode) => _get('errorToast', mode);
  static Color noticeBadWeather(ThemeMode mode) => _get('noticeBadWeather', mode);
  static Color noticeUrgent(ThemeMode mode) => _get('noticeUrgent', mode);
  static Color noticeImportant(ThemeMode mode) => _get('noticeImportant', mode);
  static Color noticeRegular(ThemeMode mode) => _get('noticeRegular', mode);
}

2. 创建主题状态管理Provider

这个类负责管理当前主题模式,处理SharedPreferences的读写,通过ChangeNotifier通知UI更新:

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';

class ThemeProvider extends ChangeNotifier {
  ThemeMode _currentMode = ThemeMode.light;
  ThemeMode get currentMode => _currentMode;

  // 初始化时读取本地保存的主题
  ThemeProvider() {
    _loadSavedTheme();
  }

  Future<void> _loadSavedTheme() async {
    final prefs = await SharedPreferences.getInstance();
    final isDark = prefs.getBool('isDarkTheme') ?? false;
    _currentMode = isDark ? ThemeMode.dark : ThemeMode.light;
    notifyListeners();
  }

  // 切换主题并保存到本地
  Future<void> toggleTheme() async {
    _currentMode = _currentMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setBool('isDarkTheme', _currentMode == ThemeMode.dark);
    notifyListeners();
  }
}

3. 在应用中配置Provider并使用动态颜色

首先在main函数中注入Provider:

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

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

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

  @override
  Widget build(BuildContext context) {
    final themeProvider = Provider.of<ThemeProvider>(context);
    return MaterialApp(
      theme: ThemeData.light(),
      darkTheme: ThemeData.dark(),
      themeMode: themeProvider.currentMode,
      home: const HomePage(),
    );
  }
}

然后在UI组件中调用动态颜色:

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

  @override
  Widget build(BuildContext context) {
    final themeMode = Provider.of<ThemeProvider>(context).currentMode;
    return Scaffold(
      backgroundColor: ThemeColors.background(themeMode),
      appBar: AppBar(
        backgroundColor: ThemeColors.primary(themeMode),
        title: Text(
          '主题切换示例',
          style: TextStyle(color: ThemeColors.primaryFont(themeMode)),
        ),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '测试文本',
              style: TextStyle(
                color: ThemeColors.secondaryFont(themeMode),
                fontSize: 18,
              ),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Provider.of<ThemeProvider>(context, listen: false).toggleTheme();
              },
              child: const Text('切换主题'),
            ),
          ],
        ),
      ),
    );
  }
}

补充说明

  • 如果追求类型安全,可以把_light和_dark换成实体类(比如LightColorConfig、DarkColorConfig),再通过ThemeColors返回对应实例,避免字符串key的潜在错误。
  • 不需要切换的颜色可以保留原静态常量,按需调整即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 14:17:23