请添加图片描述

添加提醒页面让用户创建新的提醒事项。除了基本的提醒信息,还可以设置重复周期和提醒方式。比如床垫翻转提醒可以设置每三个月重复一次。

这个页面的表单比较丰富,包括提醒信息、时间设置、提醒方式三个区块。时间选择器和 Switch 开关是这个页面的特色。

页面设计思路

添加提醒页面的设计要点:

  1. 提醒信息区块:标题、类型、关联家具
  2. 时间设置区块:日期、时间、重复周期
  3. 提醒方式区块:多个开关控制不同的提醒方式
  4. 备注区块
  5. 保存按钮

重复周期让用户可以设置定期提醒,比如每月、每季度、每年。

页面基础结构

添加提醒页面用 StatefulWidget

class AddReminderPage extends StatefulWidget {
  const AddReminderPage({super.key});
  
  State<AddReminderPage> createState() => _AddReminderPageState();
}

状态类里定义类型和重复选项:

class _AddReminderPageState extends State<AddReminderPage> {
  String _type = '保养提醒';
  String _repeat = '不重复';
  final _types = ['保养提醒', '保修到期', '清洁提醒', '其他'];
  final _repeats = ['不重复', '每周', '每月', '每季度', '每年'];

提醒类型有保养、保修、清洁等。重复周期有不重复、每周、每月、每季度、每年。

build 方法实现

build 方法构建整个页面:

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFFAF8F5),
      appBar: AppBar(
        title: const Text('添加提醒'), 
        backgroundColor: const Color(0xFF8B4513), 
        foregroundColor: Colors.white
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16.w),
        child: Column(
          children: [
            _buildSection('提醒信息', [
              _buildField('提醒标题', '请输入提醒标题', Icons.notifications),
              _buildDropdown('提醒类型', _types, _type, 
                (v) => setState(() => _type = v!)),
              _buildField('关联家具', '请选择关联的家具', Icons.chair),
            ]),

提醒信息区块包含标题、类型、关联家具三个字段。

时间设置区块

时间设置包含日期、时间、重复周期:

            SizedBox(height: 16.h),
            _buildSection('时间设置', [
              _buildDateField('提醒日期'),
              _buildTimeField('提醒时间'),
              _buildDropdown('重复', _repeats, _repeat, 
                (v) => setState(() => _repeat = v!)),
            ]),

日期用日期选择器,时间用时间选择器,重复周期用下拉框。

提醒方式区块

提醒方式用 Switch 开关控制:

            SizedBox(height: 16.h),
            _buildSection('提醒方式', [
              _buildSwitchTile('应用内通知', true),
              _buildSwitchTile('系统通知', true),
              _buildSwitchTile('提前1天提醒', false),
            ]),

三个开关分别控制应用内通知、系统通知、提前提醒。

备注和保存按钮

备注区块和保存按钮:

            SizedBox(height: 16.h),
            _buildSection('备注', [_buildNotesField()]),
            SizedBox(height: 24.h),
            _buildSaveButton(),
          ],
        ),
      ),
    );
  }

区块容器组件

_buildSection 方法:

  Widget _buildSection(String title, List<Widget> children) {
    return Container(
      padding: EdgeInsets.all(16.w),
      decoration: BoxDecoration(
        color: Colors.white, 
        borderRadius: BorderRadius.circular(16.r)
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start, 
        children: [
          Text(title, style: TextStyle(
            fontSize: 16.sp, 
            fontWeight: FontWeight.bold, 
            color: const Color(0xFF5D4037)
          )),
          SizedBox(height: 16.h),
          ...children,
        ]
      ),
    );
  }

文本输入框组件

普通文本输入框:

  Widget _buildField(String label, String hint, IconData icon) {
    return Padding(
      padding: EdgeInsets.only(bottom: 12.h),
      child: TextFormField(
        decoration: InputDecoration(
          labelText: label, 
          hintText: hint,
          prefixIcon: Icon(icon, color: const Color(0xFF8B4513)),
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.r)),
        ),
      ),
    );
  }

下拉选择框组件

类型和重复下拉框:

  Widget _buildDropdown(String label, List<String> items, String value, 
      Function(String?) onChanged) {
    return Padding(
      padding: EdgeInsets.only(bottom: 12.h),
      child: DropdownButtonFormField<String>(
        value: value,
        decoration: InputDecoration(
          labelText: label, 
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.r))
        ),
        items: items.map((i) => DropdownMenuItem(value: i, child: Text(i))).toList(),
        onChanged: onChanged,
      ),
    );
  }

日期选择器组件

日期选择器:

  Widget _buildDateField(String label) {
    return Padding(
      padding: EdgeInsets.only(bottom: 12.h),
      child: TextFormField(
        readOnly: true,
        decoration: InputDecoration(
          labelText: label,
          prefixIcon: const Icon(Icons.calendar_today, color: Color(0xFF8B4513)),
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.r)),
        ),
        onTap: () async {
          await showDatePicker(
            context: context, 
            initialDate: DateTime.now(), 
            firstDate: DateTime(2000), 
            lastDate: DateTime(2030)
          );
        },
      ),
    );
  }

时间选择器组件

时间选择器:

  Widget _buildTimeField(String label) {
    return Padding(
      padding: EdgeInsets.only(bottom: 12.h),
      child: TextFormField(
        readOnly: true,
        decoration: InputDecoration(
          labelText: label,
          prefixIcon: const Icon(Icons.access_time, color: Color(0xFF8B4513)),
          border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.r)),
        ),
        onTap: () async {
          await showTimePicker(
            context: context, 
            initialTime: TimeOfDay.now()
          );
        },
      ),
    );
  }

showTimePicker 是 Flutter 内置的时间选择器,弹出一个时钟界面让用户选择时间。

Switch 开关组件

提醒方式开关:

  Widget _buildSwitchTile(String title, bool value) {
    return Padding(
      padding: EdgeInsets.only(bottom: 8.h),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(title, style: TextStyle(fontSize: 14.sp)),
          Switch(
            value: value, 
            onChanged: (v) {}, 
            activeColor: const Color(0xFF8B4513)
          ),
        ],
      ),
    );
  }

备注输入框组件

多行备注输入框:

  Widget _buildNotesField() {
    return TextFormField(
      maxLines: 3,
      decoration: InputDecoration(
        hintText: '请输入备注信息...', 
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(10.r))
      ),
    );
  }

保存按钮组件

保存按钮:

  Widget _buildSaveButton() {
    return SizedBox(
      width: double.infinity, 
      height: 50.h,
      child: ElevatedButton(
        onPressed: () { 
          Get.back(); 
          Get.snackbar('成功', '提醒已添加', 
            backgroundColor: Colors.green, 
            colorText: Colors.white
          ); 
        },
        style: ElevatedButton.styleFrom(
          backgroundColor: const Color(0xFF8B4513), 
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.r))
        ),
        child: Text('保存', style: TextStyle(fontSize: 16.sp, color: Colors.white)),
      ),
    );
  }

重复提醒的处理

设置重复后,需要计算下次提醒时间:

DateTime _getNextReminderDate(DateTime baseDate, String repeat) {
  switch (repeat) {
    case '每周':
      return baseDate.add(Duration(days: 7));
    case '每月':
      return DateTime(baseDate.year, baseDate.month + 1, baseDate.day);
    case '每季度':
      return DateTime(baseDate.year, baseDate.month + 3, baseDate.day);
    case '每年':
      return DateTime(baseDate.year + 1, baseDate.month, baseDate.day);
    default:
      return baseDate;
  }
}

提醒完成后,如果是重复提醒,自动创建下一次提醒。

本地通知

要实现系统通知,需要用本地通知插件:

// 使用 flutter_local_notifications 插件
void _scheduleNotification(DateTime dateTime, String title, String body) {
  // 配置通知
  // 设置定时触发
}

本地通知可以在指定时间弹出系统通知,即使 App 没有打开也能收到。

小结

添加提醒页面让用户创建新的提醒事项,包括提醒信息、时间设置、提醒方式三个区块。时间选择器让用户选择日期和时间,重复周期支持定期提醒。

Switch 开关让用户可以自定义提醒方式,比如是否需要系统通知、是否提前提醒。

下一篇会讲日历视图页面的实现,用日历形式展示所有事件。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐