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

一、项目概述

本项目是基于 Flutter 跨端框架开发的智能备忘录应用,专为鸿蒙 6.0+(API20+)设备适配。通过集成 4 个鸿蒙化三方库,实现「笔记新增 / 编辑 / 删除」「富文本格式设置」「数据本地持久化」「下拉刷新同步」核心功能,无需为鸿蒙单独编写原生代码,仅通过一套 Dart 代码即可在鸿蒙设备上稳定运行。

核心技术栈

技术 / 工具 版本要求 作用说明
DevEco Studio 6.0+ 鸿蒙开发 IDE,提供 Flutter 插件支持
Flutter SDK 3.27.4-ohos 社区维护的鸿蒙适配版 Flutter
鸿蒙 SDK API20+(鸿蒙 6.0+) 应用运行的系统基础
三方库 鸿蒙适配版 实现核心功能(下文详细说明)

三方库选型(鸿蒙化适配)

三方库名称 版本 / 来源 核心作用 适配优势
shared_preferences 鸿蒙社区适配版 本地数据持久化 支持鸿蒙 Preferences API,数据不丢失
flutter_quill ^7.0.0(适配版) 富文本编辑 支持字体 / 颜色 / 列表设置,鸿蒙 UI 兼容
pull_to_refresh 鸿蒙社区分支 下拉刷新 适配鸿蒙触摸事件,无卡顿闪退
path_provider 鸿蒙适配版 文件路径获取 兼容鸿蒙文件系统,支持附件存储

二、环境搭建(新手必看)

1. 安装 DevEco Studio 6.0+

  • 下载地址:华为开发者联盟官网

  • 安装时勾选「HarmonyOS SDK API20」,自动下载适配鸿蒙 6.0 + 的系统资源

  • 安装 Flutter 插件:File → Settings → Plugins → 搜索Flutter → 安装官方插件 → 重启IDE

2. 配置 Flutter 鸿蒙 SDK

\# 1. 克隆社区维护的鸿蒙适配版 Flutter SDK(需先安装Git)

git clone -b oh-3.27.4-dev https://gitcode.com/openharmony-tpc/flutter\_flutter.git

\# 2. 配置系统环境变量(Windows示例)

\# 新建 FLUTTER\_HOME 变量,值为克隆后的SDK路径(如:D:\flutter\_flutter)

\# 在 Path 中添加:%FLUTTER\_HOME%\bin、%FLUTTER\_HOME%\bin\cache\dart-sdk\bin

\# 3. 开启鸿蒙支持

flutter config --enable-harmony

\# 4. 验证配置(终端执行)

flutter --version  # 需显示 Flutter 3.27.4-ohos 及以上版本

3. 创建鸿蒙模拟器(API20+)

  1. 打开 DevEco Studio → Tools → Device Manager

  2. 点击 New Device → 选择「Phone」→ 挑选鸿蒙 6.0 + 机型(如 Mate 70 Pro)

  3. 点击 Create 下载镜像(需联网),创建完成后点击「Start」启动模拟器

三、项目创建与配置

1. 创建 Flutter 鸿蒙项目

  1. DevEco Studio → File → New → New Project

  2. 左侧选择「Flutter」→ 右侧选择「Flutter HarmonyOS Project」

  3. 填写项目信息:

  • Project Name:flutter_harmony_memo

  • Save Location:非中文无空格路径

  • Flutter SDK Path:选择步骤 2 克隆的鸿蒙适配版 SDK

  • Minimum HarmonyOS SDK:API20(自动匹配鸿蒙 6.0+)

  1. 点击「Finish」完成创建,等待项目同步完成

2. 配置三方库依赖(pubspec.yaml)

打开项目根目录的 pubspec.yaml,替换 dependencies 节点内容(所有库均为鸿蒙适配版):

environment:

  sdk: '>=3.0.0 .0.0'

  flutter: ">=3.27.0"  # 与Flutter SDK版本匹配

dependencies:

  flutter:

    sdk: flutter

  \# 1. 本地数据持久化(鸿蒙适配版)

  shared\_preferences:

    git:

      url: "https://gitcode.com/openharmony-tpc/flutter\_packages.git"

      path: "packages/shared\_preferences/shared\_preferences"

      ref: "br\_shared\_preferences-v2.5.4\_ohos"

  \# 2. 富文本编辑(兼容鸿蒙UI)

  flutter\_quill: ^7.0.0

  \# 富文本依赖的文件路径库(鸿蒙适配版)

  path\_provider:

    git:

      url: "https://gitcode.com/openharmony-tpc/flutter\_packages.git"

      path: "packages/path\_provider/path\_provider"

      ref: "br\_path\_provider-v2.1.5\_ohos"

  \# 3. 下拉刷新(适配鸿蒙触摸事件)

  pull\_to\_refresh:

    git:

      url: "https://gitcode.com/openharmony-tpc/flutter\_packages.git"

      path: "packages/pull\_to\_refresh/pull\_to\_refresh"

      ref: "ohos-adapt"

  \# 4. 日期时间处理(纯Dart库,无需适配)

  intl: ^0.19.0

dev\_dependencies:

  flutter\_test:

    sdk: flutter

  flutter\_lints: ^3.0.0

flutter:

  uses-material-design: true  # 启用Material Design组件

3. 安装依赖与同步项目

\# 终端执行(项目根目录)

flutter clean  # 清理缓存

flutter pub get  # 下载三方库
  • 等待依赖安装完成后,点击 DevEco Studio 顶部「Sync」按钮,确保无报错

4. 配置鸿蒙权限(module.json5)

打开 ohos/entry/src/main/module.json5,添加存储权限(用于持久化备忘录数据):

{

  "module": {

    "name": "entry",

    "type": "entry",

    "srcEntry": "./ets/entryability/EntryAbility.ets",

    "description": "\$string:module\_desc",

    "mainElement": "EntryAbility",

    "deviceTypes": \["phone"],

    "deliveryWithInstall": true,

    "installationFree": false,

    "pages": "\$profile:main\_pages",

    "abilities": \[

      {

        "name": "EntryAbility",

        "srcEntry": "./ets/entryability/EntryAbility.ets",

        "description": "\$string:EntryAbility\_desc",

        "icon": "\$media:icon",

        "label": "\$string:EntryAbility\_label",

        "startWindowIcon": "\$media:icon",

        "startWindowBackground": "\$color:start\_window\_background",

        "skills": \[

          {

            "entities": \["entity.system.home"],

            "actions": \["action.system.home"]

          }

        ]

      }

    ],

    // 新增权限配置(API20+要求显式声明)

    "requestPermissions": \[

      {

        "name": "ohos.permission.WRITE\_USER\_STORAGE",

        "reason": "需要存储备忘录数据",

        "usedScene": {

          "abilities": \["EntryAbility"],

          "when": "always"

        }

      },

      {

        "name": "ohos.permission.READ\_USER\_STORAGE",

        "reason": "需要读取备忘录数据",

        "usedScene": {

          "abilities": \["EntryAbility"],

          "when": "always"

        }

      }

    ]

  }

}

四、核心代码实现(分模块讲解)

1. 数据模型封装(lib/models/memo_model.dart)

定义备忘录数据结构,统一数据格式:

import 'package:intl/intl.dart';

/// 备忘录数据模型

class MemoModel {

  final String id; // 唯一标识(避免重复)

  final String content; // 富文本内容(JSON格式存储)

  final String title; // 笔记标题(截取前20字)

  final DateTime createTime; // 创建时间

  final DateTime updateTime; // 更新时间

  bool isStarred; // 是否星标(收藏)

  MemoModel({

    required this.id,

    required this.content,

    required this.title,

    required this.createTime,

    required this.updateTime,

    this.isStarred = false,

  });

  /// 从JSON解析为模型(用于从本地存储读取)

  factory MemoModel.fromJson(Map) {

    return MemoModel(

      id: json\['id'],

      content: json\['content'],

      title: json\['title'],

      createTime: DateTime.parse(json\['createTime']),

      updateTime: DateTime.parse(json\['updateTime']),

      isStarred: json\['isStarred'] ?? false,

    );

  }

  /// 转换为JSON(用于存储到本地)

&#x20; Map\<String, dynamic> toJson() {

&#x20;   return {

&#x20;     'id': id,

&#x20;     'content': content,

&#x20;     'title': title,

&#x20;     'createTime': createTime.toIso8601String(),

&#x20;     'updateTime': updateTime.toIso8601String(),

&#x20;     'isStarred': isStarred,

&#x20;   };

&#x20; }

&#x20; /// 格式化时间显示(如:2024-05-20 14:30)

&#x20; String get formattedTime {

&#x20;   return DateFormat('yyyy-MM-dd HH:mm').format(updateTime);

&#x20; }

&#x20; /// 复制对象(用于修改时不影响原数据)

&#x20; MemoModel copyWith({

&#x20;   String? id,

&#x20;   String? content,

&#x20;   String? title,

&#x20;   DateTime? createTime,

&#x20;   DateTime? updateTime,

&#x20;   bool? isStarred,

&#x20; }) {

&#x20;   return MemoModel(

&#x20;     id: id ?? this.id,

&#x20;     content: content ?? this.content,

&#x20;     title: title ?? this.title,

&#x20;     createTime: createTime ?? this.createTime,

&#x20;     updateTime: updateTime ?? this.updateTime,

&#x20;     isStarred: isStarred ?? this.isStarred,

&#x20;   );

&#x20; }

}

2. 本地存储服务(lib/services/storage_service.dart)

基于 shared_preferences 实现数据持久化,封装增删改查方法:

import 'package:shared\_preferences/shared\_preferences.dart';

import '../models/memo\_model.dart';

/// 本地存储服务(单例模式,全局唯一)

class StorageService {

&#x20; static StorageService? \_instance;

&#x20; late SharedPreferences \_prefs;

&#x20; // 私有构造函数,防止外部创建实例

&#x20; StorageService.\_();

&#x20; /// 获取单例实例

&#x20; static FutureInstance() async {

&#x20;   if (\_instance == null) {

&#x20;     \_instance = StorageService.\_();

&#x20;     // 初始化SharedPreferences(鸿蒙适配版已处理底层调用)

&#x20;     \_instance!.\_prefs = await SharedPreferences.getInstance();

&#x20;   }

&#x20;   return \_instance!;

&#x20; }

&#x20; /// 存储键(用于标识备忘录数据)

&#x20; static const String \_memoKey = 'harmony\_flutter\_memos';

&#x20; /// 1. 获取所有备忘录

&#x20; Future\<MemoModel>> getMemos() async {

&#x20;   // 从本地读取JSON字符串(鸿蒙存储目录下)

&#x20;   final String? memoJson = \_prefs.getString(\_memoKey);

&#x20;   if (memoJson == null || memoJson.isEmpty) {

&#x20;     return \[]; // 无数据时返回空列表

&#x20;   }

&#x20;   // 解析JSON为List>,再转换为MemoModel列表

&#x20;   final List = await Future(() =>&#x20;

&#x20;     (jsonDecode(memoJson) as List>).map((e) => e as Map dynamic>).toList()

&#x20;   );

&#x20;   return jsonList.map((json) => MemoModel.fromJson(json)).toList();

&#x20; }

&#x20; /// 2. 添加/修改备忘录

&#x20; FutureMemo(MemoModel memo) async {

&#x20;   // 先获取现有所有备忘录

&#x20;   final List\<MemoModel> memos = await getMemos();

&#x20;   // 移除旧数据(根据id匹配,实现修改功能)

&#x20;   memos.removeWhere((item) => item.id == memo.id);

&#x20;   // 添加新数据

&#x20;   memos.add(memo);

&#x20;   // 转换为JSON字符串存储

&#x20;   final String jsonString = jsonEncode(memos.map((e) => e.toJson()).toList());

&#x20;   return \_prefs.setString(\_memoKey, jsonString);

&#x20; }

&#x20; /// 3. 删除备忘录

&#x20; Future> deleteMemo(String memoId) async {

&#x20;   final List> memos = await getMemos();

&#x20;   // 根据id移除对应备忘录

&#x20;   memos.removeWhere((item) => item.id == memoId);

&#x20;   // 重新存储修改后的列表

&#x20;   final String jsonString = jsonEncode(memos.map((e) => e.toJson()).toList());

&#x20;   return \_prefs.setString(\_memoKey, jsonString);

&#x20; }

&#x20; /// 4. 清空所有备忘录

&#x20; Future\<bool> clearAllMemos() async {

&#x20;   return \_prefs.remove(\_memoKey);

&#x20; }

}

3. 主页面实现(备忘录列表,lib/main.dart)

集成下拉刷新、列表展示、星标功能,使用 pull_to_refresh 实现刷新逻辑:

import 'package:flutter/material.dart';

import 'package:pull\_to\_refresh/pull\_to\_refresh.dart';

import 'models/memo\_model.dart';

import 'services/storage\_service.dart';

import 'pages/edit\_memo\_page.dart';

void main() {

&#x20; runApp(const MyApp());

}

class MyApp extends StatelessWidget {

&#x20; const MyApp({super.key});

&#x20; @override

&#x20; Widget build(BuildContext context) {

&#x20;   return MaterialApp(

&#x20;     title: 'Flutter鸿蒙智能备忘录',

&#x20;     theme: ThemeData(

&#x20;       primarySwatch: Colors.blue,

&#x20;       // 适配鸿蒙系统字体样式

&#x20;       textTheme: const TextTheme(

&#x20;         bodyLarge: TextStyle(fontSize: 18),

&#x20;         bodyMedium: TextStyle(fontSize: 16),

&#x20;       ),

&#x20;     ),

&#x20;     home: const MemoListPage(),

&#x20;     debugShowCheckedModeBanner: false, // 隐藏调试水印

&#x20;   );

&#x20; }

}

class MemoListPage extends StatefulWidget {

&#x20; const MemoListPage({super.key});

&#x20; @override

&#x20; State> createState() => \_MemoListPageState();

}

class \_MemoListPageState extends State\<MemoListPage> {

&#x20; late List\<MemoModel> \_memos = \[];

&#x20; late StorageService \_storageService;

&#x20; final RefreshController \_refreshController = RefreshController(initialRefresh: false);

&#x20; /// 初始化:获取存储服务实例 + 加载备忘录数据

&#x20; @override

&#x20; void initState() {

&#x20;   super.initState();

&#x20;   \_initStorageAndLoadMemos();

&#x20; }

&#x20; /// 初始化存储服务并加载数据

&#x20; Future \_initStorageAndLoadMemos() async {

&#x20;   \_storageService = await StorageService.getInstance();

&#x20;   await \_loadMemos();

&#x20; }

&#x20; /// 加载备忘录数据(核心方法)

&#x20; Future \_loadMemos() async {

&#x20;   final List\<MemoModel> loadedMemos = await \_storageService.getMemos();

&#x20;   // 按更新时间倒序排序(最新的在最前面)

&#x20;   loadedMemos.sort((a, b) => b.updateTime.compareTo(a.updateTime));

&#x20;   setState(() {

&#x20;     \_memos = loadedMemos;

&#x20;   });

&#x20; }

&#x20; /// 下拉刷新触发

&#x20; Future() async {

&#x20;   await \_loadMemos(); // 重新加载数据

&#x20;   \_refreshController.refreshCompleted(); // 结束刷新动画

&#x20; }

&#x20; /// 跳转到编辑页面(新增/修改)

&#x20; void \_navigateToEditPage({MemoModel? memo}) async {

&#x20;   // 等待编辑页面返回结果

&#x20;   final MemoModel? result = await Navigator.push(

&#x20;     context,

&#x20;     MaterialPageRoute(

&#x20;       builder: (context) => EditMemoPage(memo: memo),

&#x20;     ),

&#x20;   );

&#x20;   // 如果返回了备忘录数据,说明需要保存

&#x20;   if (result != null) {

&#x20;     await \_storageService.saveMemo(result);

&#x20;     await \_loadMemos(); // 重新加载列表

&#x20;   }

&#x20; }

&#x20; /// 删除备忘录

&#x20; FuturedeleteMemo(String memoId) async {

&#x20;   // 显示确认对话框(鸿蒙系统原生样式适配)

&#x20;   final bool confirm = await showDialog(

&#x20;     context: context,

&#x20;     builder: (context) => AlertDialog(

&#x20;       title: const Text('确认删除'),

&#x20;       content: const Text('是否删除该备忘录?删除后无法恢复'),

&#x20;       actions: \[

&#x20;         TextButton(

&#x20;           onPressed: () => Navigator.pop(context, false),

&#x20;           child: const Text('取消'),

&#x20;         ),

&#x20;         TextButton(

&#x20;           onPressed: () => Navigator.pop(context, true),

&#x20;           child: const Text('删除', style: TextStyle(color: Colors.red)),

&#x20;         ),

&#x20;       ],

&#x20;     ),

&#x20;   );

&#x20;   if (confirm) {

&#x20;     await \_storageService.deleteMemo(memoId);

&#x20;     await \_loadMemos(); // 重新加载列表

&#x20;   }

&#x20; }

&#x20; /// 切换星标状态

&#x20; Future> \_toggleStar(MemoModel memo) async {

&#x20;   final MemoModel updatedMemo = memo.copyWith(

&#x20;     isStarred: !memo.isStarred,

&#x20;     updateTime: DateTime.now(), // 更新时间戳

&#x20;   );

&#x20;   await \_storageService.saveMemo(updatedMemo);

&#x20;   await \_loadMemos();

&#x20; }

&#x20; @override

&#x20; Widget build(BuildContext context) {

&#x20;   return Scaffold(

&#x20;     appBar: AppBar(

&#x20;       title: const Text('智能备忘录'),

&#x20;       centerTitle: true, // 鸿蒙设备标题居中更美观

&#x20;       actions: \[

&#x20;         // 清空所有数据按钮

&#x20;         IconButton(

&#x20;           icon: const Icon(Icons.delete\_sweep),

&#x20;           onPressed: \_memos.isEmpty

&#x20;               ? null // 无数据时禁用

&#x20;               : () async {

&#x20;                   final bool confirm = await showDialog(

&#x20;                     context: context,

&#x20;                     builder: (context) => AlertDialog(

&#x20;                       title: const Text('确认清空'),

&#x20;                       content: const Text('是否删除所有备忘录?'),

&#x20;                       actions: \[

&#x20;                         TextButton(

&#x20;                           onPressed: () => Navigator.pop(context, false),

&#x20;                           child: const Text('取消'),

&#x20;                         ),

&#x20;                         TextButton(

&#x20;                           onPressed: () => Navigator.pop(context, true),

&#x20;                           child: const Text('确认', style: TextStyle(color: Colors.red)),

&#x20;                         ),

&#x20;                       ],

&#x20;                     ),

&#x20;                   );

&#x20;                   if (confirm) {

&#x20;                     await \_storageService.clearAllMemos();

&#x20;                     await \_loadMemos();

&#x20;                   }

&#x20;                 },

&#x20;         ),

&#x20;       ],

&#x20;     ),

&#x20;     body: \_buildMemoList(),

&#x20;     // 新增备忘录按钮(悬浮按钮,鸿蒙系统适配样式)

&#x20;     floatingActionButton: FloatingActionButton(

&#x20;       onPressed: () => \_navigateToEditPage(), // 无参数表示新增

&#x20;       child: const Icon(Icons.add),

&#x20;       backgroundColor: Colors.blue,

&#x20;     ),

&#x20;   );

&#x20; }

&#x20; /// 构建备忘录列表

&#x20; Widget \_buildMemoList() {

&#x20;   if (\_memos.isEmpty) {

&#x20;     // 无数据时显示空状态

&#x20;     return const Center(

&#x20;       child: Column(

&#x20;         mainAxisAlignment: MainAxisAlignment.center,

&#x20;         children: \[

&#x20;           Icon(Icons.note\_add, size: 60, color: Colors.grey),

&#x20;           SizedBox(height: 20),

&#x20;           Text('暂无备忘录,点击右下角添加', style: TextStyle(fontSize: 16, color: Colors.grey)),

&#x20;         ],

&#x20;       ),

&#x20;     );

&#x20;   }

&#x20;   // 有数据时显示下拉刷新列表

&#x20;   return SmartRefresher(

&#x20;     controller: \_refreshController,

&#x20;     onRefresh: \_onRefresh,

&#x20;     header: const WaterDropHeader(

&#x20;       complete: Icon(Icons.check, color: Colors.blue), // 刷新完成图标

&#x20;     ),

&#x20;     child: ListView.builder(

&#x20;       padding: const EdgeInsets.all(10),

&#x20;       itemCount: \_memos.length,

&#x20;       itemBuilder: (context, index) {

&#x20;         final MemoModel memo = \_memos\[index];

&#x20;         return Card(

&#x20;           elevation: 3, // 阴影效果(适配鸿蒙UI)

&#x20;           margin: const EdgeInsets.symmetric(vertical: 8),

&#x20;           child: ListTile(

&#x20;             // 星标图标

&#x20;             leading: IconButton(

&#x20;               icon: Icon(

&#x20;                 memo.isStarred ? Icons.star : Icons.star\_border,

&#x20;                 color: memo.isStarred ? Colors.yellow : Colors.grey,

&#x20;               ),

&#x20;               onPressed: () => \_toggleStar(memo),

&#x20;             ),

&#x20;             // 备忘录标题

&#x20;             title: Text(

&#x20;               memo.title,

&#x20;               maxLines: 1,

&#x20;               overflow: TextOverflow.ellipsis,

&#x20;               style: const TextStyle(fontWeight: FontWeight.w500),

&#x20;             ),

&#x20;             // 时间和摘要

&#x20;             subtitle: Column(

&#x20;               crossAxisAlignment: CrossAxisAlignment.start,

&#x20;               children: \[

&#x20;                 const SizedBox(height: 4),

&#x20;                 Text(

&#x20;                   memo.formattedTime,

&#x20;                   style: const TextStyle(fontSize: 12, color: Colors.grey),

&#x20;                 ),

&#x20;               ],

&#x20;             ),

&#x20;             // 点击进入编辑页面

&#x20;             onTap: () => \_navigateToEditPage(memo: memo),

&#x20;             // 侧滑删除

&#x20;             trailing: IconButton(

&#x20;               icon: const Icon(Icons.delete, color: Colors.red),

&#x20;               onPressed: () => \_deleteMemo(memo.id),

&#x20;             ),

&#x20;           ),

&#x20;         );

&#x20;       },

&#x20;     ),

&#x20;   );

&#x20; }

}

4. 编辑页面实现(富文本编辑,lib/pages/edit_memo_page.dart)

基于 flutter_quill 实现富文本编辑功能,支持字体、颜色、列表等格式:

import 'package:flutter/material.dart';

import 'package:flutter\_quill/flutter\_quill.dart';

import 'package:intl/intl.dart';

import '../models/memo\_model.dart';

import 'dart:convert';

class EditMemoPage extends StatefulWidget {

&#x20; final MemoModel? memo; // 可选参数:编辑时传入已有备忘录,新增时为null

&#x20; const EditMemoPage({super.key, this.memo});

&#x20; @override

&#x20; StatePage> createState() => \_EditMemoPageState();

}

class \_EditMemoPageState extends State> {

&#x20; late QuillController \_quillController; // 富文本控制器

&#x20; late bool \_isEditing; // 是否为编辑模式

&#x20; @override

&#x20; void initState() {

&#x20;   super.initState();

&#x20;   \_isEditing = widget.memo != null;

&#x20;   // 初始化富文本控制器

&#x20;   if (\_isEditing) {

&#x20;     // 编辑模式:从备忘录内容加载富文本数据

&#x20;     final List> docJson = jsonDecode(widget.memo!.content);

&#x20;     \_quillController = QuillController(

&#x20;       document: Document.fromJson(docJson),

&#x20;       selection: const TextSelection.collapsed(offset: 0),

&#x20;     );

&#x20;   } else {

&#x20;     // 新增模式:创建空文档

&#x20;     \_quillController = QuillController(

&#x20;       document: Document(),

&#x20;       selection: const TextSelection.collapsed(offset: 0),

&#x20;     );

&#x20;   }

&#x20; }

&#x20; /// 提取富文本内容作为标题(前20字)

&#x20; String \_extractTitle() {

&#x20;   final String plainText = \_quillController.document.toPlainText();

&#x20;   if (plainText.isEmpty) {

&#x20;     return \_isEditing ? widget.memo!.title : '无标题备忘录';

&#x20;   }

&#x20;   return plainText.length > 20

&#x20;       ? '\${plainText.substring(0, 20)}...'

&#x20;       : plainText;

&#x20; }

&#x20; /// 保存备忘录

&#x20; void \_saveMemo() {

&#x20;   // 转换富文本内容为JSON字符串

&#x20;   final String contentJson = jsonEncode(\_quillController.document.toJson());

&#x20;   final MemoModel newMemo = MemoModel(

&#x20;     id: \_isEditing ? widget.memo!.id : DateTime.now().millisecondsSinceEpoch.toString(), // 唯一ID(时间戳)

&#x20;     content: contentJson,

&#x20;     title: \_extractTitle(),

&#x20;     createTime: \_isEditing ? widget.memo!.createTime : DateTime.now(),

&#x20;     updateTime: DateTime.now(),

&#x20;     isStarred: \_isEditing ? widget.memo!.isStarred : false,

&#x20;   );

&#x20;   // 返回上一页并传递新备忘录数据

&#x20;   Navigator.pop(context, newMemo);

&#x20; }

&#x20; @override

&#x20; Widget build(BuildContext context) {

&#x20;   return Scaffold(

&#x20;     appBar: AppBar(

&#x20;       title: Text(\_isEditing ? '编辑备忘录' : '新增备忘录'),

&#x20;       centerTitle: true,

&#x20;       actions: \[

&#x20;         // 保存按钮

&#x20;         TextButton(

&#x20;           onPressed: \_saveMemo,

&#x20;           child: const Text('保存', style: TextStyle(color: Colors.white, fontSize: 16)),

&#x20;         ),

&#x20;       ],

&#x20;     ),

&#x20;     body: Column(

&#x20;       children: \[

&#x20;         // 富文本工具栏(字体、颜色、列表等)

&#x20;         QuillToolbar.basic(

&#x20;           controller: \_quillController,

&#x20;           showUnderLineButton: true,

&#x20;           showBoldButton: true,

&#x20;           showItalicButton: true,

&#x20;           showColorButton: true,

&#x20;           showListCheck: true,

&#x20;           showListBullet: true,

&#x20;           showListOrdered: true,

&#x20;           toolbarIconSize: 24, // 适配鸿蒙设备图标大小

&#x20;           padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),

&#x20;         ),

&#x20;         // 富文本编辑区域

&#x20;         Expanded(

&#x20;           child: Padding(

&#x20;             padding: const EdgeInsets.all(16.0),

&#x20;             child: SingleChildScrollView(

&#x20;               child: QuillEditor.basic(

&#x20;                 controller: \_quillController,

&#x20;                 readOnly: false,

&#x20;                 padding: EdgeInsets.zero,

&#x20;                 // 适配鸿蒙设备文本样式

&#x20;                 customStyles: DefaultStyles(

&#x20;                   paragraph: DefaultTextBlockStyle(

&#x20;                     const TextStyle(fontSize: 18, height: 1.5),

&#x20;                     const Tuple2(16, 16),

&#x20;                     const Tuple2(0, 0),

&#x20;                     null,

&#x20;                   ),

&#x20;                 ),

&#x20;               ),

&#x20;             ),

&#x20;           ),

&#x20;         ),

&#x20;       ],

&#x20;     ),

&#x20;   );

&#x20; }

}

五、项目运行与测试

1. 运行项目

  1. 确保鸿蒙模拟器已启动(或连接鸿蒙 6.0 + 真机,开启 USB 调试)

  2. 终端执行运行命令:

flutter run -d   # device\_id可通过flutter devices命令查看

\# 若仅连接一台设备,可直接执行:flutter run
  1. 等待编译完成,应用将自动安装到鸿蒙设备上

2. 功能测试清单

测试项 操作步骤 预期结果
新增备忘录 点击右下角 + 号 → 输入内容 → 点击保存 列表新增一条备忘录,数据持久化
富文本编辑 选中文字 → 使用工具栏设置粗体 / 颜色 / 列表 文本样式正常生效,保存后不丢失
星标功能 点击列表项左侧星标图标 星标状态切换(黄色 / 灰色),数据保存
下拉刷新 列表页面下拉 刷新列表,显示最新数据
编辑备忘录 点击列表项 → 修改内容 → 保存 原备忘录内容更新,时间戳刷新
删除备忘录 点击列表项右侧删除图标 → 确认 备忘录从列表移除,本地数据删除
清空所有 点击顶部清空按钮 → 确认 所有备忘录删除,显示空状态
数据持久化 关闭应用 → 重新打开 之前的备忘录数据完整保留

六、常见问题排查

1. 构建失败:三方库下载失败

  • 解决方案:检查网络连接,执行 flutter pub get --verbose 查看详细日志,若 Git 仓库访问失败,可替换为国内镜像源

  • 替代方案:从 OpenHarmony TPC 社区 手动下载三方库,放置到项目 packages 目录下

2. 运行闪退:权限未配置

  • 解决方案:检查 module.json5 中的 requestPermissions 配置,确保已添加存储权限,重新编译运行

3. 富文本编辑异常:字体错乱

  • 解决方案:在 QuillEditor 中明确指定 customStyles,统一文本样式,避免鸿蒙系统字体冲突

4. 数据不持久化:存储键错误

  • 解决方案:确保 StorageService 中的 _memoKey 唯一,未与其他应用冲突,执行 flutter clean 后重新运行
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐