Flutter待办APP自定义提醒弹窗实现方案咨询
实现自定义Todo提醒弹窗的分步指导
1. 搭建弹窗基础结构
用Flutter原生的showModalBottomSheet实现底部弹窗(更贴合移动端交互习惯),基础框架如下:
typedef ReminderCallback = void Function(DateTime? reminderTime, RepeatType repeatType); void showReminderModal(BuildContext context, ReminderCallback onConfirm) { showModalBottomSheet( context: context, isScrollControlled: true, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(16)), ), builder: (context) => StatefulBuilder( builder: (context, setState) { DateTime? selectedDateTime; RepeatType selectedRepeat = RepeatType.none; return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ const Text("设置提醒", style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), // 后续添加时间选择、重复选项、操作按钮 ], ), ), ); }, ), ); } // 定义重复类型枚举 enum RepeatType { none, daily, weekly, monthly, yearly }
2. 实现特定时间选择功能
组合原生showDatePicker和showTimePicker,让用户选择日期+时间,用intl包格式化时间显示(需在pubspec.yaml添加intl: ^0.18.1):
// 在Column的children中添加时间选择ListTile const SizedBox(height: 16), ListTile( title: Text(selectedDateTime != null ? DateFormat("yyyy-MM-dd HH:mm").format(selectedDateTime) : "选择提醒时间"), trailing: const Icon(Icons.arrow_forward_ios), onTap: () async { final date = await showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365)), ); if (date != null) { final time = await showTimePicker( context: context, initialTime: TimeOfDay.fromDateTime(DateTime.now()), ); if (time != null) { setState(() { selectedDateTime = DateTime( date.year, date.month, date.day, time.hour, time.minute, ); }); } } }, ),
3. 实现重复提醒选项
用RadioListTile实现「不重复/每天/每周/每月/每年」的单选选项:
// 在时间选择组件后添加重复选项区域 const SizedBox(height: 16), const Text("重复提醒", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), RadioListTile<RepeatType>( title: const Text("不重复"), value: RepeatType.none, groupValue: selectedRepeat, onChanged: (value) => setState(() => selectedRepeat = value!), ), RadioListTile<RepeatType>( title: const Text("每天"), value: RepeatType.daily, groupValue: selectedRepeat, onChanged: (value) => setState(() => selectedRepeat = value!), ), RadioListTile<RepeatType>( title: const Text("每周"), value: RepeatType.weekly, groupValue: selectedRepeat, onChanged: (value) => setState(() => selectedRepeat = value!), ), RadioListTile<RepeatType>( title: const Text("每月"), value: RepeatType.monthly, groupValue: selectedRepeat, onChanged: (value) => setState(() => selectedRepeat = value!), ), RadioListTile<RepeatType>( title: const Text("每年"), value: RepeatType.yearly, groupValue: selectedRepeat, onChanged: (value) => setState(() => selectedRepeat = value!), ),
4. 添加确认/取消按钮
在弹窗底部添加操作按钮,点击确认时将选择结果通过回调返回给父组件:
// 在重复选项区域后添加按钮行 const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text("取消"), ), const SizedBox(width: 8), ElevatedButton( onPressed: () { onConfirm(selectedDateTime, selectedRepeat); Navigator.pop(context); }, child: const Text("确认"), ), ], ),
5. 整合到Todo应用
在你的Todo添加/编辑页面中调用弹窗:
ElevatedButton( onPressed: () { showReminderModal(context, (reminderTime, repeatType) { // 这里将提醒设置保存到你的Todo数据模型中 // 示例:todo.reminderTime = reminderTime; // todo.repeatType = repeatType; }); }, child: const Text("设置提醒"), ),
可选优化
- 若需要更美观的滚轮式时间选择,可替换为
CupertinoDatePicker实现iOS风格交互; - 针对「每周重复」可扩展多选星期几的功能;
- 当Todo已有提醒时,弹窗默认填充已有设置,添加「清除提醒」选项;
- 处理时区问题,确保提醒时间在不同时区下的准确性。
内容的提问来源于stack exchange,提问作者Virtual Tech
相关产品推荐
相关产品推荐

