flutter_for_openharmony口腔护理app实战+提醒设置实现

开篇
良好的口腔护理习惯需要持之以恒,而提醒功能正是帮助用户养成习惯的得力助手。通过设置定时提醒,用户可以在合适的时间收到刷牙、用药、检查等提示,从而更好地维护口腔健康。
本文将介绍如何在 Flutter 中实现一个功能丰富的提醒设置页面,涵盖刷牙提醒、用药提醒、检查提醒等多种类型的提醒管理。
页面功能规划
提醒设置页面需要支持以下功能模块:
- 刷牙提醒:早中晚三个时段的刷牙提醒开关
- 用药提醒:展示用户设置的用药提醒列表
- 检查提醒:定期检查和洗牙的提醒设置
- 自定义提醒:支持用户添加个性化的提醒
页面结构实现
提醒设置页面采用 StatelessWidget,数据通过 Consumer 从 AppProvider 获取:
class ReminderPage extends StatelessWidget {
const ReminderPage({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('提醒设置')),
body: Consumer<AppProvider>(
builder: (context, provider, _) {
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
使用 SingleChildScrollView 确保内容较多时可以滚动查看,crossAxisAlignment 设为 start 让标题左对齐。
刷牙提醒模块
刷牙提醒是最基础也是最重要的提醒类型,我们设置了早中晚三个时段:
const Text('刷牙提醒',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
_buildReminderCard(
icon: Icons.wb_sunny,
title: '早晨刷牙',
time: '07:00',
isEnabled: true,
),
_buildReminderCard(
icon: Icons.wb_cloudy,
title: '中午刷牙',
time: '12:30',
isEnabled: false,
),
_buildReminderCard(
icon: Icons.nightlight,
title: '晚上刷牙',
time: '21:00',
isEnabled: true,
),
每个时段使用不同的图标来表示:太阳代表早晨,云朵代表中午,月亮代表晚上。这种视觉设计让用户一目了然。
提醒卡片组件
提醒卡片是一个可复用的组件,接收图标、标题、时间和启用状态作为参数:
Widget _buildReminderCard({
required IconData icon,
required String title,
required String time,
required bool isEnabled,
}) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
卡片使用白色背景和圆角设计,与应用整体风格保持一致。底部留有间距,让多个卡片之间有适当的视觉分隔。
卡片内部布局采用 Row 实现水平排列:
child: Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: const Color(0xFF26A69A).withOpacity(0.1),
shape: BoxShape.circle,
),
child: Icon(icon, color: const Color(0xFF26A69A)),
),
const SizedBox(width: 16),
图标放在圆形容器中,使用主题色的浅色版本作为背景,营造出柔和的视觉效果。
标题和时间垂直排列:
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
Text(time, style: TextStyle(color: Colors.grey.shade600)),
],
),
),
使用 Expanded 让文字区域占据剩余空间,标题加粗显示,时间使用灰色次要文字。
开关控件放在最右侧:
Switch(
value: isEnabled,
onChanged: (value) {},
activeColor: const Color(0xFF26A69A),
),
],
),
);
}
Switch 组件的激活颜色设为主题色,与整体设计协调。目前 onChanged 为空实现,实际项目中需要连接到状态管理。
用药提醒模块
用药提醒展示用户设置的药物提醒列表:
const SizedBox(height: 24),
const Text('用药提醒',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
...provider.medicineReminders.map(
(reminder) => _buildMedicineCard(reminder)),
使用展开运算符将提醒列表映射为卡片组件。数据来自 AppProvider 中的 medicineReminders 列表。
用药提醒卡片的实现:
Widget _buildMedicineCard(dynamic reminder) {
return Container(
margin: const EdgeInsets.only(bottom: 12),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.orange.withOpacity(0.1),
shape: BoxShape.circle,
),
child: const Icon(Icons.medication, color: Colors.orange),
),
用药提醒使用橙色作为主色调,与刷牙提醒的绿色形成区分,帮助用户快速识别不同类型的提醒。
药物信息的展示:
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(reminder.name,
style: const TextStyle(fontWeight: FontWeight.bold)),
Text('${reminder.dosage} · ${reminder.times.join(", ")}',
style: TextStyle(color: Colors.grey.shade600)),
],
),
),
Switch(
value: reminder.isActive,
onChanged: (value) {},
activeColor: const Color(0xFF26A69A),
),
],
),
);
}
药物名称作为标题,剂量和服用时间作为副标题。使用 join 方法将时间数组转换为逗号分隔的字符串。
检查提醒模块
定期的口腔检查和洗牙对于预防口腔疾病非常重要:
const SizedBox(height: 24),
const Text('检查提醒',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 12),
_buildReminderCard(
icon: Icons.medical_services,
title: '定期检查',
time: '每6个月',
isEnabled: true,
),
_buildReminderCard(
icon: Icons.cleaning_services,
title: '洗牙提醒',
time: '每6个月',
isEnabled: true,
),
检查提醒复用了刷牙提醒的卡片组件,只是图标和内容不同。这种组件复用的方式让代码更加简洁。
添加自定义提醒
页面底部提供了添加自定义提醒的按钮:
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: () => _showAddReminderDialog(context),
icon: const Icon(Icons.add),
label: const Text('添加自定义提醒'),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF26A69A),
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
),
],
),
);
},
),
);
}
按钮使用 ElevatedButton.icon 组合图标和文字,宽度设为 double.infinity 占满整行,增加点击区域。
添加提醒对话框
点击添加按钮后弹出选择对话框:
void _showAddReminderDialog(BuildContext context) {
showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: const Text('添加提醒'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
leading: const Icon(Icons.brush, color: Color(0xFF26A69A)),
title: const Text('刷牙提醒'),
onTap: () {
Navigator.pop(ctx);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('功能开发中')));
},
),
对话框使用 Column 配合 mainAxisSize: MainAxisSize.min 让高度自适应内容。每个选项使用 ListTile 实现,包含图标、标题和点击事件。
其他提醒类型的选项:
ListTile(
leading: const Icon(Icons.medication, color: Colors.orange),
title: const Text('用药提醒'),
onTap: () {
Navigator.pop(ctx);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('功能开发中')));
},
),
ListTile(
leading: const Icon(Icons.medical_services, color: Colors.blue),
title: const Text('检查提醒'),
onTap: () {
Navigator.pop(ctx);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('功能开发中')));
},
),
],
),
),
);
}
每种提醒类型使用不同的颜色图标,与页面中的卡片颜色保持一致。点击后关闭对话框并显示提示。
数据模型设计
用药提醒的数据模型定义:
class MedicineReminder {
final String id;
final String name;
final String dosage;
final List<String> times;
final bool isActive;
MedicineReminder({
String? id,
required this.name,
required this.dosage,
required this.times,
this.isActive = true,
}) : id = id ?? DateTime.now().millisecondsSinceEpoch.toString();
}
模型包含药物名称、剂量、服用时间列表和激活状态。时间使用字符串列表存储,便于展示多个服用时间点。
Provider 数据管理
在 AppProvider 中管理提醒数据:
List<MedicineReminder> _medicineReminders = [];
List<MedicineReminder> get medicineReminders => _medicineReminders;
void addMedicineReminder(MedicineReminder reminder) {
_medicineReminders.add(reminder);
notifyListeners();
}
void toggleMedicineReminder(String id) {
final index = _medicineReminders.indexWhere((r) => r.id == id);
if (index != -1) {
final old = _medicineReminders[index];
_medicineReminders[index] = MedicineReminder(
id: old.id,
name: old.name,
dosage: old.dosage,
times: old.times,
isActive: !old.isActive,
);
notifyListeners();
}
}
提供添加提醒和切换提醒状态的方法,每次操作后通知界面更新。
测试数据初始化
为了开发调试,在 initTestData 中添加测试数据:
void initTestData() {
_medicineReminders = [
MedicineReminder(
name: '漱口水',
dosage: '10ml',
times: ['08:00', '20:00'],
),
MedicineReminder(
name: '口腔喷雾',
dosage: '2次',
times: ['12:00'],
isActive: false,
),
];
}
测试数据包含两条用药提醒,一条激活一条未激活,便于测试不同状态的显示效果。
本地通知集成思路
实际项目中,提醒功能需要集成本地通知。Flutter 中常用 flutter_local_notifications 插件:
// 初始化通知插件
final FlutterLocalNotificationsPlugin notifications =
FlutterLocalNotificationsPlugin();
Future<void> initNotifications() async {
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
const iosSettings = DarwinInitializationSettings();
const settings = InitializationSettings(
android: androidSettings,
iOS: iosSettings,
);
await notifications.initialize(settings);
}
这段代码展示了通知插件的初始化过程,需要分别配置 Android 和 iOS 的设置。
设置定时通知的示例:
Future<void> scheduleReminder(String title, TimeOfDay time) async {
final now = DateTime.now();
var scheduledDate = DateTime(
now.year, now.month, now.day,
time.hour, time.minute
);
if (scheduledDate.isBefore(now)) {
scheduledDate = scheduledDate.add(const Duration(days: 1));
}
await notifications.zonedSchedule(
0,
'口腔护理提醒',
title,
tz.TZDateTime.from(scheduledDate, tz.local),
const NotificationDetails(
android: AndroidNotificationDetails(
'reminder_channel',
'提醒通知',
importance: Importance.high,
),
),
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
uiLocalNotificationDateInterpretation:
UILocalNotificationDateInterpretation.absoluteTime,
matchDateTimeComponents: DateTimeComponents.time,
);
}
matchDateTimeComponents: DateTimeComponents.time 设置让通知每天在指定时间重复触发。
Switch 组件状态绑定
将 Switch 组件与实际数据绑定:
Switch(
value: isEnabled,
onChanged: (value) {
// 更新提醒状态
provider.updateReminderStatus(reminderId, value);
},
activeColor: const Color(0xFF26A69A),
),
当用户切换开关时,调用 Provider 的方法更新状态,界面会自动响应变化。
时间选择器集成
添加提醒时需要选择提醒时间:
Future<TimeOfDay?> selectTime(BuildContext context) async {
return showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
builder: (context, child) {
return Theme(
data: Theme.of(context).copyWith(
colorScheme: const ColorScheme.light(
primary: Color(0xFF26A69A),
),
),
child: child!,
);
},
);
}
通过 builder 参数自定义时间选择器的主题色,保持与应用风格一致。
用户体验细节
在设计提醒设置页面时,我们注意了以下用户体验细节:
分类清晰:将提醒按类型分组,每组有明确的标题,用户可以快速找到需要的设置。
视觉区分:不同类型的提醒使用不同的颜色图标,刷牙用绿色,用药用橙色,检查用蓝色。
操作便捷:开关控件放在卡片右侧,用户可以快速开启或关闭提醒,无需进入详情页。
反馈及时:操作后显示 SnackBar 提示,让用户知道操作结果。
扩展功能建议
基于当前实现,可以考虑添加以下功能:
- 自定义时间:允许用户修改每个提醒的具体时间
- 重复设置:支持设置每天、工作日、周末等不同的重复模式
- 提醒铃声:允许用户选择不同的提醒铃声
- 免打扰时段:设置特定时段内不发送提醒
总结
本文详细介绍了口腔护理 App 中提醒设置功能的实现。通过合理的分类设计和组件复用,我们构建了一个功能完善、易于使用的提醒管理页面。关键技术点包括:
- 使用
Consumer监听数据变化 - 通过参数化组件实现卡片复用
- 使用
Switch组件实现开关控制 - 通过对话框提供添加入口
提醒功能是帮助用户养成良好习惯的重要工具,希望本文的实现思路对你有所帮助。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)