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

Flutter应用实现亮色/暗色/系统主题切换及状态保存方案求助

解决方案

要实现无状态管理库的主题切换+持久化,我们可以用StatefulWidget配合shared_preferences插件来完成,具体步骤如下:

1. 添加依赖

在pubspec.yaml中加入shared_preferences:

dependencies:
  flutter:
    sdk: flutter
  shared_preferences: ^2.2.2 # 使用最新版本即可

2. 修改MyApp为StatefulWidget

将原来的StatelessWidget改为StatefulWidget,负责管理主题模式、读取本地存储和更新主题:

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

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

  static void setThemeMode(BuildContext context, ThemeMode mode) {
    final state = context.findAncestorStateOfType<_MyAppState>()!;
    state._updateThemeMode(mode);
  }

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.system;

  @override
  void initState() {
    super.initState();
    _loadSavedTheme();
  }

  // 从本地存储读取保存的主题设置
  Future<void> _loadSavedTheme() async {
    final prefs = await SharedPreferences.getInstance();
    final themeIndex = prefs.getInt('theme_mode');
    setState(() {
      _themeMode = ThemeMode.values[themeIndex ?? 2]; // 2对应ThemeMode.system
    });
  }

  // 更新主题模式并保存到本地
  Future<void> _updateThemeMode(ThemeMode mode) async {
    final prefs = await SharedPreferences.getInstance();
    await prefs.setInt('theme_mode', mode.index);
    setState(() {
      _themeMode = mode;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(scaffoldBackgroundColor: Colors.white),
      darkTheme: ThemeData(scaffoldBackgroundColor: Colors.black),
      themeMode: _themeMode,
      home: const HomePage(),
    );
  }
}

3. 修改HomePage的按钮逻辑

在HomePage的按钮点击事件中调用MyApp提供的方法来切换主题:

class HomePage extends StatelessWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () {
              MyApp.setThemeMode(context, ThemeMode.dark);
            },
            child: const Text('暗色模式'),
          ),
          ElevatedButton(
            onPressed: () {
              MyApp.setThemeMode(context, ThemeMode.light);
            },
            child: const Text('亮色模式'),
          ),
          ElevatedButton(
            onPressed: () {
              MyApp.setThemeMode(context, ThemeMode.system);
            },
            child: const Text('跟随系统'),
          ),
        ],
      ),
    );
  }
}

关键说明

  • 给MyApp添加静态方法setThemeMode,让子页面可以直接触发主题更新
  • _loadSavedTheme会在App启动时读取本地存储的主题设置,保证重启后保留用户选择
  • 使用ThemeMode.values[index]将存储的整数转换为枚举值,ThemeMode.system的索引为2,作为默认 fallback

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 04:40:26