🎨 开源鸿蒙 Flutter 实战|深色模式切换保姆级教程(鸿蒙兼容 + 可直接运行)

欢迎加入开源鸿蒙跨平台社https://openharmonycrosplatform.csdn.net

哈喽宝子们!我是刚学跨平台开发的大一新生😆 这次给我的鸿蒙 FlutterAPP 加上了深色模式切换功能,不仅能一键切换浅色 / 深色主题,还能自动保存主题偏好,下次打开 APP 自动恢复,体验超丝滑!
全程用的都是OpenHarmony 官方兼容清单里的库,完全没有兼容问题,新手也能直接抄作业!

先给大家汇报一下这次的成果✨
✅ 深色 / 浅色主题一键切换
✅ 主题偏好本地持久化保存
✅ 切换时丝滑过渡动画
✅ 鸿蒙虚拟机实机验证,无闪退卡顿
✅ 代码极简,新手友好度拉满

一、用到的鸿蒙兼容库
选库的时候我特意翻了 OpenHarmony 官方的三方库兼容清单,就怕选到不兼容的库踩坑,最终选了两个对新手极度友好、鸿蒙适配拉满的库:
鸿蒙兼容库
直接在pubspec.yaml里加上依赖,执行flutter pub get就能用啦:

name: flutter_hm_dark_mode_demo
description: 开源鸿蒙Flutter深色模式实战项目
version: 1.0.0+1

environment:
  sdk: '>=3.0.0 <4.0.0'

dependencies:
  flutter:
    sdk: flutter
  dio: ^5.4.0
  flutter_animate: ^4.5.0
  animations: ^2.0.11
  # 核心库:状态管理+本地存储 鸿蒙完美适配
  provider: ^6.1.1
  shared_preferences: ^2.3.2

flutter:
  uses-material-design: true

二、核心功能实现

2.1 第一步:创建主题管理 Provider
用 provider 来管理主题状态,是 Flutter 官方推荐的轻量级状态管理方案,代码超简单,新手也能看懂。
在lib目录下新建providers文件夹,创建theme_provider.dart文件:

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

/// 主题管理Provider 鸿蒙适配版
class ThemeProvider extends ChangeNotifier {
  // 本地存储的key
  static const String _themeKey = 'is_dark_mode';
  // SharedPreferences实例
  late SharedPreferences _prefs;

  // 当前主题模式:false=浅色,true=深色
  bool _isDarkMode = false;
  bool get isDarkMode => _isDarkMode;

  /// 初始化:从本地读取保存的主题偏好
  Future<void> init() async {
    _prefs = await SharedPreferences.getInstance();
    // 读取本地存储的主题,默认浅色模式
    _isDarkMode = _prefs.getBool(_themeKey) ?? false;
    notifyListeners();
  }

  /// 切换主题
  void toggleTheme() {
    _isDarkMode = !_isDarkMode;
    // 保存到本地
    _prefs.setBool(_themeKey, _isDarkMode);
    // 通知UI更新
    notifyListeners();
  }

  /// 获取当前主题数据
  ThemeData get currentTheme {
    return _isDarkMode ? darkTheme : lightTheme;
  }

  /// 浅色主题配置
  static final ThemeData lightTheme = ThemeData(
    brightness: Brightness.light,
    primarySwatch: Colors.purple,
    scaffoldBackgroundColor: Colors.white,
    cardColor: Colors.white,
    textTheme: const TextTheme(
      bodyLarge: TextStyle(color: Colors.black87),
      bodyMedium: TextStyle(color: Colors.black54),
    ),
    appBarTheme: const AppBarTheme(
      backgroundColor: Colors.purple,
      foregroundColor: Colors.white,
      elevation: 0,
    ),
    bottomNavigationBarTheme: const BottomNavigationBarThemeData(
      selectedItemColor: Colors.purple,
      unselectedItemColor: Colors.grey,
      backgroundColor: Colors.white,
    ),
  );

  /// 深色主题配置
  static final ThemeData darkTheme = ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.purple,
    scaffoldBackgroundColor: const Color(0xFF121212), // Material标准深色背景
    cardColor: const Color(0xFF1E1E1E),
    textTheme: const TextTheme(
      bodyLarge: TextStyle(color: Colors.white),
      bodyMedium: TextStyle(color: Colors.white70),
    ),
    appBarTheme: const AppBarTheme(
      backgroundColor: Color(0xFF1E1E1E),
      foregroundColor: Colors.white,
      elevation: 0,
    ),
    bottomNavigationBarTheme: const BottomNavigationBarThemeData(
      selectedItemColor: Colors.purple,
      unselectedItemColor: Colors.grey,
      backgroundColor: Color(0xFF1E1E1E),
    ),
  );
}

2.3 第三步:在 “我的” 页面添加主题切换开关
修改lib/pages/mine_page.dart,添加主题切换卡片,用 Switch 组件实现一键切换,同时加上丝滑的动画效果:

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

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

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("个人中心"), centerTitle: true),
      body: ListView(
        children: [
          // 用户信息区域
          Container(
            padding: const EdgeInsets.all(20),
            child: const Row(
              children: [
                CircleAvatar(radius: 35, backgroundImage: NetworkImage("https://picsum.photos/200")),
                SizedBox(width: 16),
                Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text("鸿蒙开发者", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                    Text("计算机大一新生 | 跨平台开发", style: TextStyle(color: Colors.grey)),
                  ],
                ),
              ],
            ),
          ),
          const SizedBox(height: 10),
          // 主题切换卡片
          Consumer<ThemeProvider>(
            builder: (context, themeProvider, child) {
              return Card(
                margin: const EdgeInsets.symmetric(horizontal: 12),
                child: ListTile(
                  leading: Icon(
                    themeProvider.isDarkMode ? Icons.dark_mode : Icons.light_mode,
                    color: Theme.of(context).primaryColor,
                  ),
                  title: const Text("外观模式"),
                  subtitle: Text(themeProvider.isDarkMode ? "深色模式" : "浅色模式"),
                  trailing: Switch(
                    value: themeProvider.isDarkMode,
                    onChanged: (value) {
                      // 切换主题
                      themeProvider.toggleTheme();
                    },
                    activeColor: Theme.of(context).primaryColor,
                  ),
                ),
              );
            },
          ),
          const SizedBox(height: 10),
          // 其他功能菜单
          const ListTile(leading: Icon(Icons.star), title: Text("我的收藏")),
          const ListTile(leading: Icon(Icons.history), title: Text("浏览历史")),
          const ListTile(leading: Icon(Icons.thumb_up), title: Text("我的点赞")),
          const ListTile(leading: Icon(Icons.settings), title: Text("设置中心")),
          const ListTile(leading: Icon(Icons.help), title: Text("帮助反馈")),
        ],
      ),
    );
  }
}

三、鸿蒙适配核心要点
作为新手,这次实现深色模式也踩了好几个鸿蒙专属的小坑,整理出来给大家避避坑:
1.版本选择:必须用稳定版,provider 6.1.1、shared_preferences 2.3.2,Flutter SDK 3.16 + 鸿蒙适配版,低版本会出现本地存储读取失败的问题

2.初始化时机:必须在main函数中先调用WidgetsFlutterBinding.ensureInitialized(),再初始化 SharedPreferences,否则会在鸿蒙设备上出现初始化异常

3.深色主题配色:推荐使用 Material 标准的深色背景色0xFF121212,卡片色0xFF1E1E1E,在鸿蒙设备上显示效果最好,不会出现过暗或过亮的问题

4.权限说明:shared_preferences 是纯本地存储,不需要在鸿蒙里申请任何额外权限,仅需保留之前的网络权限就完全够用

5.主题切换动画:Flutter 官方的themeAnimationDuration和themeAnimationCurve在鸿蒙设备上完美支持,不需要自己做额外适配

四、鸿蒙虚拟机运行验证
一键运行命令

cd ohos
hvigorw assembleHap -p product=default -p buildMode=debug
hdc install -r entry/build/default/outputs/default/entry-default-unsigned.hap
hdc shell aa start -a EntryAbility -b com.example.demo1

虚拟机运行效果展示
虚拟机运行效果展示
五、新手总结与后续拓展
作为刚学 Flutter 和鸿蒙开发的大一新生,这次深色模式切换功能的实现真的让我超有成就感!原来只需要用 provider 和 shared_preferences 两个简单的库,就能实现这么实用的功能,而且全程没有遇到太复杂的兼容问题,开源鸿蒙的生态对新手也越来越友好了🥰

当然我还有很多要学习的地方,这次的深色模式只是基础实现,后续我还会研究:
1.跟随系统深色模式自动切换
2.自定义主题色切换
3.深色模式下的图片适配
4.更多鸿蒙原生能力的接入与适配

也会持续给大家分享我的新手实战内容,和大家一起在开源鸿蒙的生态里慢慢进步✨

如果这篇文章有帮到你,或者你也有新手开发的小技巧,欢迎在评论区和我交流呀!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐