精选文章

Flutter 主题系统

2022-08-23 · 主题

主题系统的目标是统一视觉与可维护性。本文基于 provider + shared_preferences 给出一套可复用的主题实现范式:主题定义、状态管理、持久化与切换。

0. 依赖

dependencies:
  provider: ^6.0.5
  shared_preferences: ^2.1.2

1. 定义主题模型

enum AppThemeType { light, dark }

class AppTheme {
  static ThemeData light = ThemeData(
    brightness: Brightness.light,
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
  );

  static ThemeData dark = ThemeData(
    brightness: Brightness.dark,
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal, brightness: Brightness.dark),
  );
}

2. 主题状态管理

class ThemeStore extends ChangeNotifier {
  AppThemeType _type = AppThemeType.light;
  AppThemeType get type => _type;

  ThemeData get theme => _type == AppThemeType.light ? AppTheme.light : AppTheme.dark;

  void setTheme(AppThemeType type) {
    _type = type;
    notifyListeners();
  }
}

3. 注入与应用

ChangeNotifierProvider(
  create: (_) => ThemeStore(),
  child: Consumer<ThemeStore>(
    builder: (_, store, __) => MaterialApp(
      theme: store.theme,
    ),
  ),
)

4. 持久化主题

class ThemeStore extends ChangeNotifier {
  AppThemeType _type = AppThemeType.light;

  Future<void> load() async {
    final prefs = await SharedPreferences.getInstance();
    final saved = prefs.getString('theme');
    _type = saved == 'dark' ? AppThemeType.dark : AppThemeType.light;
    notifyListeners();
  }

  Future<void> setTheme(AppThemeType type) async {
    _type = type;
    final prefs = await SharedPreferences.getInstance();
    await prefs.setString('theme', type == AppThemeType.dark ? 'dark' : 'light');
    notifyListeners();
  }
}

5. UI 切换按钮

IconButton(
  icon: const Icon(Icons.brightness_6),
  onPressed: () {
    final store = context.read<ThemeStore>();
    store.setTheme(store.type == AppThemeType.dark ? AppThemeType.light : AppThemeType.dark);
  },
)

6. 实践清单

  • 主题模型统一定义
  • Provider 管理主题状态
  • 持久化用户偏好
  • 全局入口切换

总结

主题系统是设计系统的技术承载。统一入口、状态管理与持久化,才能让主题可维护。

JJ

作者简介

专注于内容创作、产品策略与设计实践。欢迎交流合作。

上一篇 下一篇