#
前言
提醒设置页面让用户可以配置各种健康提醒,比如体重记录提醒、血压测量提醒、饮水提醒、睡眠提醒等。定时提醒能帮助用户养成良好的健康记录习惯。
这篇文章会讲解提醒设置页面的实现,包括提醒项列表和开关控制等核心功能。
页面整体结构
提醒设置页面使用 StatefulWidget,因为需要管理各个提醒的开关状态。
dart
class ReminderSettingsPage extends StatefulWidget {
const ReminderSettingsPage({super.key});
@override
State<ReminderSettingsPage> createState() => _ReminderSettingsPageState();
}
class _ReminderSettingsPageState extends State<ReminderSettingsPage> {
bool _weightReminder = true;
bool _bpReminder = true;
bool _waterReminder = false;
bool _sleepReminder = true;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFFAFAFC),
appBar: AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_rounded, size: 20.w),
onPressed: () => Get.back()
),
title: Text('提醒设置', style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.w600)),
centerTitle: true,
),
body: SingleChildScrollView(
padding: EdgeInsets.all(20.w),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20.r)
),
child: Column(
children: [
_buildReminderItem('体重记录', '每天 08:00', _weightReminder, (v) => setState(() => _weightReminder = v)),
_buildDivider(),
_buildReminderItem('血压测量', '每天 07:00', _bpReminder, (v) => setState(() => _bpReminder = v)),
_buildDivider(),
_buildReminderItem('饮水提醒', '每2小时', _waterReminder, (v) => setState(() => _waterReminder = v)),
_buildDivider(),
_buildReminderItem('睡眠提醒', '每天 22:30', _sleepReminder, (v) => setState(() => _sleepReminder = v)),
],
),
),
),
);
}
}
页面使用白色卡片包裹所有提醒项,提醒项之间用分隔线隔开。每个提醒项有独立的开关状态,通过 setState 更新。
提醒项组件
提醒项组件展示提醒名称、时间和开关控制。
dart
Widget _buildReminderItem(String title, String time, bool value, Function(bool) onChanged) {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: TextStyle(
fontSize: 15.sp,
color: const Color(0xFF1A1A2E)
)),
SizedBox(height: 2.h),
Text(time, style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[500]
)),
],
),
),
Switch(
value: value,
onChanged: onChanged,
activeColor: const Color(0xFF6C63FF)
),
],
),
);
}
Widget _buildDivider() {
return Divider(
height: 1,
indent: 16.w,
endIndent: 16.w,
color: Colors.grey[100]
);
}
每个提醒项左边显示名称和时间,右边是开关。开关使用应用主题色 #6C63FF,和整体设计风格保持一致。
分隔线左右各留出 16.w 的边距,不会顶到边缘,视觉效果更好。
时间选择功能
点击提醒项可以修改提醒时间:
dart
void _showTimePicker(BuildContext context, String title, TimeOfDay currentTime) async {
final TimeOfDay? picked = await showTimePicker(
context: context,
initialTime: currentTime,
builder: (context, child) {
return Theme(
data: Theme.of(context).copyWith(
colorScheme: const ColorScheme.light(
primary: Color(0xFF6C63FF),
onPrimary: Colors.white,
surface: Colors.white,
onSurface: Color(0xFF1A1A2E),
),
),
child: child!,
);
},
);
if (picked != null) {
// 更新提醒时间
final formatted = '${picked.hour.toString().padLeft(2, '0')}:${picked.minute.toString().padLeft(2, '0')}';
// 保存新时间
}
}
使用 Flutter 内置的 showTimePicker,通过 Theme 自定义颜色和应用主题保持一致。
提醒频率选择
有些提醒需要选择频率,比如饮水提醒:
dart
void _showFrequencyPicker(BuildContext context) {
final frequencies = ['每小时', '每2小时', '每3小时', '每4小时'];
int selectedIndex = 1;
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20.r)),
),
builder: (context) => StatefulBuilder(
builder: (context, setState) => Container(
padding: EdgeInsets.all(20.w),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('选择提醒频率', style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
color: const Color(0xFF1A1A2E),
)),
SizedBox(height: 20.h),
...frequencies.asMap().entries.map((entry) {
final isSelected = entry.key == selectedIndex;
return GestureDetector(
onTap: () {
setState(() => selectedIndex = entry.key);
},
child: Container(
margin: EdgeInsets.only(bottom: 10.h),
padding: EdgeInsets.symmetric(vertical: 14.h),
decoration: BoxDecoration(
color: isSelected
? const Color(0xFF6C63FF).withOpacity(0.1)
: Colors.grey[50],
borderRadius: BorderRadius.circular(12.r),
border: isSelected
? Border.all(color: const Color(0xFF6C63FF))
: null,
),
child: Center(
child: Text(entry.value, style: TextStyle(
fontSize: 15.sp,
color: isSelected
? const Color(0xFF6C63FF)
: const Color(0xFF1A1A2E),
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
)),
),
),
);
}),
SizedBox(height: 10.h),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
Navigator.pop(context);
// 保存频率设置
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF6C63FF),
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
),
child: Text('确定', style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w600,
color: Colors.white,
)),
),
),
],
),
),
),
);
}
频率选择器用底部弹出菜单,选中的选项用紫色边框和背景高亮显示。
提醒开关状态保存
开关状态变化时需要保存到本地:
dart
void _saveReminderState(String type, bool enabled) async {
// 保存到 SharedPreferences
// final prefs = await SharedPreferences.getInstance();
// await prefs.setBool('reminder_$type', enabled);
if (enabled) {
// 注册本地通知
_scheduleNotification(type);
} else {
// 取消本地通知
_cancelNotification(type);
}
}
void _scheduleNotification(String type) {
// 根据类型设置不同的通知
switch (type) {
case 'weight':
// 每天 08:00 提醒记录体重
break;
case 'bp':
// 每天 07:00 提醒测量血压
break;
case 'water':
// 每2小时提醒喝水
break;
case 'sleep':
// 每天 22:30 提醒准备睡觉
break;
}
}
void _cancelNotification(String type) {
// 取消对应类型的通知
}
开关状态保存到本地存储,同时注册或取消本地通知。
提醒详情设置
可以为每个提醒添加更详细的设置:
dart
Widget _buildReminderDetailItem(
String title,
String time,
String frequency,
bool value,
Function(bool) onChanged,
VoidCallback onTap,
) {
return GestureDetector(
onTap: onTap,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: TextStyle(
fontSize: 15.sp,
color: const Color(0xFF1A1A2E),
)),
SizedBox(height: 4.h),
Row(
children: [
Text(time, style: TextStyle(
fontSize: 12.sp,
color: Colors.grey[500],
)),
SizedBox(width: 8.w),
Container(
padding: EdgeInsets.symmetric(horizontal: 6.w, vertical: 2.h),
decoration: BoxDecoration(
color: const Color(0xFF6C63FF).withOpacity(0.1),
borderRadius: BorderRadius.circular(4.r),
),
child: Text(frequency, style: TextStyle(
fontSize: 10.sp,
color: const Color(0xFF6C63FF),
)),
),
],
),
],
),
),
Switch(
value: value,
onChanged: onChanged,
activeColor: const Color(0xFF6C63FF),
),
],
),
),
);
}
详细设置项除了时间,还显示频率标签。点击整行可以进入详细设置页面。
提醒测试
可以添加一个测试按钮,让用户预览提醒效果:
dart
Widget _buildTestButton() {
return Container(
margin: EdgeInsets.only(top: 20.h),
child: TextButton(
onPressed: () {
// 发送测试通知
_sendTestNotification();
},
child: Text('发送测试提醒', style: TextStyle(
fontSize: 14.sp,
color: const Color(0xFF6C63FF),
)),
),
);
}
void _sendTestNotification() {
// 发送一条测试通知
Get.snackbar(
'测试提醒',
'这是一条测试提醒消息',
snackPosition: SnackPosition.TOP,
backgroundColor: const Color(0xFF6C63FF),
colorText: Colors.white,
duration: const Duration(seconds: 3),
);
}
测试按钮让用户可以预览提醒的效果,确认设置是否正确。
免打扰时段
可以设置免打扰时段,在这个时间段内不发送提醒:
dart
Widget _buildDoNotDisturbSection() {
return Container(
margin: EdgeInsets.only(top: 20.h),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('免打扰时段', style: TextStyle(
fontSize: 15.sp,
fontWeight: FontWeight.w500,
color: const Color(0xFF1A1A2E),
)),
Switch(
value: true,
onChanged: (v) {},
activeColor: const Color(0xFF6C63FF),
),
],
),
SizedBox(height: 8.h),
Text('23:00 - 07:00', style: TextStyle(
fontSize: 13.sp,
color: Colors.grey[500],
)),
SizedBox(height: 4.h),
Text('在此时段内不会发送任何提醒', style: TextStyle(
fontSize: 11.sp,
color: Colors.grey[400],
)),
],
),
);
}
免打扰时段让用户可以在睡眠时间避免被打扰,提升使用体验。
小结
提醒设置页面通过开关控制和时间选择,让用户可以灵活配置各种健康提醒。
核心设计要点包括:提醒项使用统一的布局和开关样式,时间和频率选择使用底部弹出菜单,免打扰时段避免不必要的打扰。这些设计让用户能轻松管理自己的健康提醒,养成良好的记录习惯。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net