【flutter for open harmony】第三方库Flutter 鸿蒙版 简易记事本 实战指南(适配 1.0.0)✨
记事本是应用中最基础也是最实用的功能之一。无论是快速记录想法、待办事项、还是临时笔记,都需要一个简单易用的记事本工具。本文将介绍如何在Flutter鸿蒙应用中实现一个支持创建、编辑、删除的简易记事本组件。本文详细介绍了如何在Flutter鸿蒙应用中实现一个功能完善的简易记事本组件。通过合理的架构设计和清晰的代码实现,我们成功创建了一个支持创建、编辑、删除、时间戳记录的实用组件。该组件可以广泛应用于
Flutter实战:开源鸿蒙简易记事本组件
Flutter 三方库 cached_network_image 的鸿蒙化适配与实战指南
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
本文详细介绍如何在Flutter鸿蒙应用中实现一个功能完善的简易记事本,支持笔记的创建、编辑、删除和时间戳记录。
一、前言
记事本是应用中最基础也是最实用的功能之一。无论是快速记录想法、待办事项、还是临时笔记,都需要一个简单易用的记事本工具。本文将介绍如何在Flutter鸿蒙应用中实现一个支持创建、编辑、删除的简易记事本组件。
二、效果展示

2.1 功能特性
| 功能 | 描述 |
|---|---|
| 笔记创建 | 输入内容保存新笔记 |
| 笔记编辑 | 修改已有笔记内容 |
| 笔记删除 | 确认后删除笔记 |
| 时间戳 | 记录笔记创建时间 |
| 空状态 | 无笔记时显示提示 |
| 编辑模式 | 区分新建和编辑状态 |
三、项目背景与目标
3.1 项目背景
在日常生活和工作中,我们经常需要快速记录一些信息。一个简单易用的记事本可以帮助用户随时记录想法,提高工作效率。
3.2 项目目标
- 实现笔记的增删改功能
- 支持时间戳记录
- 提供友好的用户界面
- 支持鸿蒙平台运行
四、技术架构设计
4.1 整体架构
┌─────────────────────────────────────┐
│ UI Layer (Widgets) │
│ ┌──────────┐ ┌──────────┐ │
│ │ TextField│ │ ListView │ │
│ └──────────┘ └──────────┘ │
├─────────────────────────────────────┤
│ State Management │
│ ┌──────────────────────────────┐ │
│ │ StatefulWidget + State │ │
│ └──────────────────────────────┘ │
├─────────────────────────────────────┤
│ Business Logic │
│ ┌────────────┐ ┌───────────────┐ │
│ │ Note │ │ Note │ │
│ │ Manager │ │ Model │ │
│ └────────────┘ └───────────────┘ │
└─────────────────────────────────────┘
4.2 核心数据结构
final TextEditingController _textController = TextEditingController();
final List<NoteItem> _notes = [];
int? _editingIndex;
class NoteItem {
final String content;
final DateTime createdAt;
NoteItem({
required this.content,
required this.createdAt,
});
}
五、详细实现
5.1 Flutter端实现
import 'package:flutter/material.dart';
class SimpleNotepadPage extends StatefulWidget {
const SimpleNotepadPage({super.key});
State<SimpleNotepadPage> createState() => _SimpleNotepadPageState();
}
class _SimpleNotepadPageState extends State<SimpleNotepadPage> {
final TextEditingController _textController = TextEditingController();
final List<NoteItem> _notes = [];
int? _editingIndex;
void dispose() {
_textController.dispose();
super.dispose();
}
void _saveNote() {
final text = _textController.text.trim();
if (text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('请输入内容')),
);
return;
}
setState(() {
if (_editingIndex != null) {
_notes[_editingIndex!] = NoteItem(
content: text,
createdAt: DateTime.now(),
);
_editingIndex = null;
} else {
_notes.insert(
0,
NoteItem(
content: text,
createdAt: DateTime.now(),
),
);
}
_textController.clear();
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('保存成功')),
);
}
void _editNote(int index) {
setState(() {
_editingIndex = index;
_textController.text = _notes[index].content;
});
}
void _deleteNote(int index) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('删除笔记'),
content: const Text('确定要删除这条笔记吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
ElevatedButton(
onPressed: () {
setState(() {
_notes.removeAt(index);
});
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已删除')),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: const Text('删除'),
),
],
),
);
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('简易记事本'),
centerTitle: true,
backgroundColor: Colors.blueGrey,
foregroundColor: Colors.white,
),
body: Column(
children: [
Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blueGrey.withOpacity(0.1),
border: Border(
bottom: BorderSide(color: Colors.grey[300]!),
),
),
child: Column(
children: [
TextField(
controller: _textController,
maxLines: 4,
decoration: InputDecoration(
hintText: '输入笔记内容...',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
),
filled: true,
fillColor: Colors.white,
),
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: ElevatedButton.icon(
onPressed: _saveNote,
icon: Icon(_editingIndex != null ? Icons.update : Icons.save),
label: Text(_editingIndex != null ? '更新' : '保存'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueGrey,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
),
),
),
if (_editingIndex != null) ...[
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: () {
setState(() {
_editingIndex = null;
_textController.clear();
});
},
icon: const Icon(Icons.cancel),
label: const Text('取消'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
),
),
],
],
),
],
),
),
Expanded(
child: _notes.isEmpty
? const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.note_add, size: 64, color: Colors.grey),
SizedBox(height: 16),
Text(
'暂无笔记',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
)
: ListView.builder(
padding: const EdgeInsets.all(16),
itemCount: _notes.length,
itemBuilder: (context, index) {
final note = _notes[index];
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
contentPadding: const EdgeInsets.all(16),
title: Text(
note.content,
maxLines: 3,
overflow: TextOverflow.ellipsis,
),
subtitle: Padding(
padding: const EdgeInsets.only(top: 8),
child: Text(
'${note.createdAt.year}-${note.createdAt.month.toString().padLeft(2, '0')}-${note.createdAt.day.toString().padLeft(2, '0')} ${note.createdAt.hour.toString().padLeft(2, '0')}:${note.createdAt.minute.toString().padLeft(2, '0')}',
style: TextStyle(color: Colors.grey[600], fontSize: 12),
),
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.edit, color: Colors.blue),
onPressed: () => _editNote(index),
),
IconButton(
icon: const Icon(Icons.delete, color: Colors.red),
onPressed: () => _deleteNote(index),
),
],
),
),
);
},
),
),
],
),
);
}
}
class NoteItem {
final String content;
final DateTime createdAt;
NoteItem({
required this.content,
required this.createdAt,
});
}
5.2 UI界面实现
UI界面采用Material Design 3设计风格,主要包含以下组件:
- 输入区域:使用TextField组件,支持多行输入
- 操作按钮:使用Row布局放置保存/更新和取消按钮
- 笔记列表:使用ListView.builder展示笔记卡片
- 空状态:使用Column组件显示空状态提示
六、核心功能解析
6.1 笔记保存
区分新建和编辑模式:
void _saveNote() {
final text = _textController.text.trim();
if (text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('请输入内容')),
);
return;
}
setState(() {
if (_editingIndex != null) {
_notes[_editingIndex!] = NoteItem(
content: text,
createdAt: DateTime.now(),
);
_editingIndex = null;
} else {
_notes.insert(
0,
NoteItem(
content: text,
createdAt: DateTime.now(),
),
);
}
_textController.clear();
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('保存成功')),
);
}
6.2 笔记编辑
进入编辑模式:
void _editNote(int index) {
setState(() {
_editingIndex = index;
_textController.text = _notes[index].content;
});
}
6.3 笔记删除
使用确认对话框:
void _deleteNote(int index) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('删除笔记'),
content: const Text('确定要删除这条笔记吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
ElevatedButton(
onPressed: () {
setState(() {
_notes.removeAt(index);
});
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('已删除')),
);
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.red,
foregroundColor: Colors.white,
),
child: const Text('删除'),
),
],
),
);
}
6.4 时间戳格式化
格式化显示时间:
'${note.createdAt.year}-${note.createdAt.month.toString().padLeft(2, '0')}-${note.createdAt.day.toString().padLeft(2, '0')} ${note.createdAt.hour.toString().padLeft(2, '0')}:${note.createdAt.minute.toString().padLeft(2, '0')}'
七、实际应用场景
7.1 快速笔记
快速记录临时想法、待办事项等。
7.2 会议记录
记录会议要点和决议。
7.3 学习笔记
记录学习内容和知识点。
7.4 购物清单
记录购物清单和待买物品。
八、优化建议
8.1 数据持久化
- 使用SharedPreferences保存笔记
- 使用SQLite数据库存储
- 支持云端同步
8.2 功能扩展
- 支持笔记分类
- 添加笔记搜索
- 支持笔记标签
- 添加笔记提醒
8.3 用户体验优化
- 支持富文本编辑
- 添加笔记导出功能
- 支持笔记分享
- 添加笔记排序
九、常见问题与解决方案
9.1 数据丢失问题
问题:应用关闭后笔记丢失
解决方案:使用SharedPreferences或SQLite持久化保存笔记
9.2 编辑状态问题
问题:编辑时删除笔记导致索引错误
解决方案:删除时检查是否在编辑状态,重置编辑索引
9.3 长文本显示问题
问题:长文本显示不完整
解决方案:使用maxLines和TextOverflow.ellipsis限制显示行数
十、总结
本文详细介绍了如何在Flutter鸿蒙应用中实现一个功能完善的简易记事本组件。通过合理的架构设计和清晰的代码实现,我们成功创建了一个支持创建、编辑、删除、时间戳记录的实用组件。该组件可以广泛应用于快速笔记、会议记录、学习笔记等场景,为用户提供便捷的笔记记录服务。
十一、参考资料
更多推荐




所有评论(0)