Flutter for OpenHarmony生活助手App实战:待办事项管理实现

待办事项管理是提升工作效率的重要工具。一个好的待办事项功能应该让用户能够快速添加任务、标记完成状态,并且能够按优先级和分类来组织任务。今天我来分享一下如何实现这个功能。
功能设计
在设计待办事项功能时,我主要考虑了以下几个方面:
首先是任务的展示,我在顶部放了一个统计区域,显示全部任务数、已完成数和未完成数,让用户对自己的任务情况一目了然。
其次是任务的管理,每个任务都可以标记完成状态、设置优先级、添加分类。用户可以通过滑动删除任务,这种交互方式很符合移动端的使用习惯。
最后是任务的添加,点击右上角的加号按钮就能快速添加新任务,整个流程非常简洁。
页面结构实现
让我先看看整体的代码结构:
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
class TodoListPage extends StatefulWidget {
const TodoListPage({super.key});
State<TodoListPage> createState() => _TodoListPageState();
}
class _TodoListPageState extends State<TodoListPage> {
final List<Map<String, dynamic>> todos = [
{'title': '完成项目报告', 'completed': false, 'priority': 'high', 'category': '工作'},
{'title': '去超市买菜', 'completed': false, 'priority': 'medium', 'category': '生活'},
{'title': '健身房锻炼', 'completed': true, 'priority': 'low', 'category': '健康'},
{'title': '阅读30分钟', 'completed': false, 'priority': 'medium', 'category': '学习'},
];
Widget build(BuildContext context) {
final completedCount = todos.where((t) => t['completed']).length;
return Scaffold(
appBar: AppBar(
title: const Text('待办事项'),
actions: [
IconButton(
icon: const Icon(Icons.add),
onPressed: _showAddDialog,
),
],
),
body: Column(
children: [
Container(
padding: EdgeInsets.all(20.w),
color: Colors.blue[50],
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('全部', '${todos.length}', Colors.blue),
_buildStatItem('已完成', '$completedCount', Colors.green),
_buildStatItem('未完成', '${todos.length - completedCount}', Colors.orange),
],
),
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(16.w),
itemCount: todos.length,
itemBuilder: (context, index) {
return _buildTodoCard(todos[index], index);
},
),
),
],
),
);
}
}
这个页面使用了StatefulWidget,因为需要管理任务列表的状态。顶部是统计区域,下面是任务列表。
统计区域设计
统计区域让用户能够快速了解任务的整体情况:
Widget _buildStatItem(String label, String value, Color color) {
return Column(
children: [
Text(
value,
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.bold,
color: color,
),
),
SizedBox(height: 4.h),
Text(label, style: TextStyle(fontSize: 12.sp, color: Colors.grey)),
],
);
}
每个统计项都包含一个数字和一个标签。数字用大号字体和彩色显示,非常醒目。全部任务用蓝色,已完成用绿色,未完成用橙色,这种颜色区分让信息更加清晰。
任务卡片实现
任务卡片是整个功能的核心,它需要展示任务的所有信息并支持交互:
Widget _buildTodoCard(Map<String, dynamic> todo, int index) {
Color priorityColor = Colors.grey;
if (todo['priority'] == 'high') priorityColor = Colors.red;
if (todo['priority'] == 'medium') priorityColor = Colors.orange;
return Dismissible(
key: Key(todo['title']),
background: Container(
color: Colors.red,
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20.w),
child: const Icon(Icons.delete, color: Colors.white),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
setState(() {
todos.removeAt(index);
});
},
child: Container(
margin: EdgeInsets.only(bottom: 12.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r),
),
child: Row(
children: [
Checkbox(
value: todo['completed'],
onChanged: (value) {
setState(() {
todos[index]['completed'] = value;
});
},
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
todo['title'],
style: TextStyle(
fontSize: 14.sp,
decoration: todo['completed'] ? TextDecoration.lineThrough : null,
),
),
SizedBox(height: 4.h),
Text(
todo['category'],
style: TextStyle(fontSize: 12.sp, color: Colors.grey),
),
],
),
),
Container(
width: 8.w,
height: 8.w,
decoration: BoxDecoration(
color: priorityColor,
shape: BoxShape.circle,
),
),
],
),
),
);
}
这个任务卡片的设计很有意思。我使用了Dismissible组件来实现滑动删除功能,用户向左滑动任务卡片就能看到红色的删除背景,继续滑动就会删除任务。
每个任务卡片包含一个复选框、任务标题、分类标签和优先级指示器。复选框用来标记任务是否完成,当任务完成时,标题会显示删除线效果。
优先级用一个小圆点来表示,高优先级是红色,中优先级是橙色,低优先级是灰色。这种设计既简洁又直观。
添加任务对话框
用户需要能够快速添加新任务,我实现了一个简单的对话框:
void _showAddDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('添加待办'),
content: TextField(
decoration: const InputDecoration(
hintText: '输入待办事项',
border: OutlineInputBorder(),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('添加成功')),
);
},
child: const Text('添加'),
),
],
),
);
}
这个对话框很简单,只有一个输入框和两个按钮。在实际应用中,你可以添加更多的选项,比如选择优先级、设置截止日期、添加备注等。
数据模型设计
为了更好地管理任务数据,我建议定义一个Todo模型:
class Todo {
final String id;
final String title;
final bool completed;
final String priority; // 'high', 'medium', 'low'
final String category;
final DateTime? dueDate;
final String? note;
Todo({
required this.id,
required this.title,
this.completed = false,
this.priority = 'medium',
required this.category,
this.dueDate,
this.note,
});
Todo copyWith({
String? id,
String? title,
bool? completed,
String? priority,
String? category,
DateTime? dueDate,
String? note,
}) {
return Todo(
id: id ?? this.id,
title: title ?? this.title,
completed: completed ?? this.completed,
priority: priority ?? this.priority,
category: category ?? this.category,
dueDate: dueDate ?? this.dueDate,
note: note ?? this.note,
);
}
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
'completed': completed,
'priority': priority,
'category': category,
'dueDate': dueDate?.toIso8601String(),
'note': note,
};
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
id: json['id'],
title: json['title'],
completed: json['completed'],
priority: json['priority'],
category: json['category'],
dueDate: json['dueDate'] != null ? DateTime.parse(json['dueDate']) : null,
note: json['note'],
);
}
这个模型包含了任务的所有必要信息,并提供了copyWith方法来方便地更新任务属性。
数据持久化
任务数据需要持久化存储,我建议使用SQLite或SharedPreferences:
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
class TodoService {
static const String _keyTodos = 'todos';
// 保存任务列表
static Future<void> saveTodos(List<Todo> todos) async {
final prefs = await SharedPreferences.getInstance();
final jsonList = todos.map((t) => t.toJson()).toList();
await prefs.setString(_keyTodos, jsonEncode(jsonList));
}
// 获取任务列表
static Future<List<Todo>> getTodos() async {
final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString(_keyTodos);
if (jsonString == null) return [];
final jsonList = jsonDecode(jsonString) as List;
return jsonList.map((json) => Todo.fromJson(json)).toList();
}
// 添加任务
static Future<void> addTodo(Todo todo) async {
final todos = await getTodos();
todos.add(todo);
await saveTodos(todos);
}
// 更新任务
static Future<void> updateTodo(Todo todo) async {
final todos = await getTodos();
final index = todos.indexWhere((t) => t.id == todo.id);
if (index != -1) {
todos[index] = todo;
await saveTodos(todos);
}
}
// 删除任务
static Future<void> deleteTodo(String id) async {
final todos = await getTodos();
todos.removeWhere((t) => t.id == id);
await saveTodos(todos);
}
}
这个服务类提供了完整的CRUD操作,可以方便地管理任务数据。
任务排序和筛选
用户可能需要按不同的方式查看任务,我们可以添加排序和筛选功能:
class TodoController {
List<Todo> _todos = [];
// 按优先级排序
List<Todo> sortByPriority() {
final priorityOrder = {'high': 0, 'medium': 1, 'low': 2};
return _todos..sort((a, b) =>
priorityOrder[a.priority]!.compareTo(priorityOrder[b.priority]!)
);
}
// 按截止日期排序
List<Todo> sortByDueDate() {
return _todos..sort((a, b) {
if (a.dueDate == null) return 1;
if (b.dueDate == null) return -1;
return a.dueDate!.compareTo(b.dueDate!);
});
}
// 筛选未完成的任务
List<Todo> getIncompleteTodos() {
return _todos.where((t) => !t.completed).toList();
}
// 按分类筛选
List<Todo> getTodosByCategory(String category) {
return _todos.where((t) => t.category == category).toList();
}
// 搜索任务
List<Todo> searchTodos(String keyword) {
return _todos.where((t) =>
t.title.toLowerCase().contains(keyword.toLowerCase())
).toList();
}
}
这些方法让用户能够更灵活地管理和查看任务。
任务提醒功能
对于有截止日期的任务,我们可以添加提醒功能:
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
class TodoReminderService {
static final FlutterLocalNotificationsPlugin _notifications =
FlutterLocalNotificationsPlugin();
static Future<void> scheduleReminder(Todo todo) async {
if (todo.dueDate == null) return;
// 在截止日期前一天提醒
final reminderTime = todo.dueDate!.subtract(const Duration(days: 1));
await _notifications.zonedSchedule(
todo.id.hashCode,
'任务提醒',
'明天要完成:${todo.title}',
TZDateTime.from(reminderTime, local),
const NotificationDetails(
android: AndroidNotificationDetails(
'todo_reminder',
'任务提醒',
channelDescription: '提醒您完成待办任务',
importance: Importance.high,
),
),
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
);
}
}
这个服务可以在任务截止日期前发送提醒通知。
性能优化
当任务数量很多时,需要注意性能优化:
第一,使用分页加载。不要一次性加载所有任务,而是先加载最近的50条,用户滚动到底部时再加载更多。
第二,使用虚拟滚动。ListView.builder本身就支持虚拟滚动,只渲染可见区域的任务。
第三,优化setState的调用。不要在每次数据变化时都调用setState,可以使用防抖动机制。
扩展功能
基于这个待办事项功能,还可以添加很多实用的特性:
比如添加子任务功能,让用户可以把大任务分解成多个小任务。
或者添加任务模板,用户可以保存常用的任务模板,下次直接使用。
还可以加入番茄钟功能,帮助用户专注完成任务。
另外,可以添加任务统计,展示用户的完成率、效率趋势等数据。
总结
待办事项管理是一个看似简单但很实用的功能。通过合理的设计和实现,它能够真正帮助用户提升工作效率。
在开发过程中,我特别注重用户体验。滑动删除、复选框标记、优先级指示,这些细节都让功能更加易用。同时,数据的持久化和提醒功能也保证了功能的实用性。
希望这篇文章能帮助你实现一个优秀的待办事项管理功能。记住,好的工具不仅要功能完善,更要简单易用。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)