在这里插入图片描述

养猫需要记住的事情太多,喂食、驱虫、疫苗…稍不注意就会忘记。今天我们来实现提醒列表页面,分类展示今日提醒、即将到来的提醒,支持开关控制和删除操作。


功能需求

提醒列表页面需要实现:

  • 分类展示今日提醒和即将到来的提醒
  • 显示全部提醒列表
  • 支持开关启用/禁用提醒
  • 支持删除提醒
  • 空状态友好提示

这些功能组合起来,就是一个完整的提醒管理页面。


依赖引入

首先导入需要的包:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:intl/intl.dart';
import '../../providers/reminder_provider.dart';
import '../../models/reminder_model.dart';
import 'add_reminder_screen.dart';

ReminderProvider专门管理提醒数据。
intl用于日期时间的格式化显示。


无状态组件

提醒列表不需要维护额外状态:

class ReminderListScreen extends StatelessWidget {
  const ReminderListScreen({super.key});

数据由Provider管理,页面本身不需要状态。
StatelessWidget更简洁高效。


页面结构

build方法构建整体布局:

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('提醒管理')),
      body: Consumer<ReminderProvider>(
        builder: (context, provider, child) {
          final reminders = provider.reminders;

Consumer监听ReminderProvider的变化。
获取所有提醒列表。


空状态处理

没有提醒时显示引导界面:

          if (reminders.isEmpty) {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(Icons.alarm, size: 80.sp, color: Colors.grey[300]),
                  SizedBox(height: 16.h),
                  Text('暂无提醒', style: TextStyle(color: Colors.grey[600])),
                ],
              ),
            );
          }

闹钟图标暗示提醒主题。
灰色调表示空状态。


分类获取提醒

获取今日和即将到来的提醒:

          final todayReminders = provider.getTodayReminders();
          final upcomingReminders = provider.getUpcomingReminders();

getTodayReminders返回今天的提醒。
getUpcomingReminders返回未来几天的提醒。


分类列表展示

用ListView展示分类后的提醒:

          return ListView(
            padding: EdgeInsets.all(16.w),
            children: [
              if (todayReminders.isNotEmpty) ...[
                Text('今日提醒', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
                SizedBox(height: 8.h),
                ...todayReminders.map((r) => _buildReminderCard(context, r, provider)),
                SizedBox(height: 16.h),
              ],

条件渲染,有今日提醒才显示这个分组。
展开运算符…将提醒列表映射为卡片。

即将到来的提醒:

              if (upcomingReminders.isNotEmpty) ...[
                Text('即将到来', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
                SizedBox(height: 8.h),
                ...upcomingReminders.map((r) => _buildReminderCard(context, r, provider)),
                SizedBox(height: 16.h),
              ],

同样的模式展示即将到来的提醒。
分组标题用粗体突出显示。

全部提醒:

              Text('全部提醒', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
              SizedBox(height: 8.h),
              ...reminders.map((r) => _buildReminderCard(context, r, provider)),
            ],
          );
        },
      ),

最后显示全部提醒列表。
用户可以查看所有设置的提醒。


悬浮添加按钮

页面底部的FAB:

      floatingActionButton: FloatingActionButton(
        onPressed: () => Navigator.push(context, MaterialPageRoute(
          builder: (_) => const AddReminderScreen(),
        )),
        backgroundColor: Colors.orange,
        child: const Icon(Icons.add),
      ),
    );
  }

点击跳转到添加提醒页面。
橙色与App主题一致。


提醒卡片组件

构建单条提醒的卡片:

  Widget _buildReminderCard(BuildContext context, ReminderModel reminder, ReminderProvider provider) {
    return Card(
      margin: EdgeInsets.only(bottom: 8.h),
      child: ListTile(
        leading: CircleAvatar(
          backgroundColor: _getTypeColor(reminder.type).withOpacity(0.1),
          child: Icon(_getTypeIcon(reminder.type), color: _getTypeColor(reminder.type), size: 20.sp),
        ),

Card提供阴影和圆角效果。
CircleAvatar显示类型对应的图标。

标题显示:

        title: Text(
          reminder.title,
          style: TextStyle(
            decoration: reminder.isEnabled ? null : TextDecoration.lineThrough,
            color: reminder.isEnabled ? null : Colors.grey,
          ),
        ),

禁用的提醒用删除线和灰色显示。
视觉上区分启用和禁用状态。

副标题信息:

        subtitle: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('${reminder.typeString} · ${reminder.repeatString}'),
            Text(DateFormat('yyyy-MM-dd HH:mm').format(reminder.dateTime)),
          ],
        ),

显示提醒类型、重复规则和时间。
两行信息让内容更清晰。


操作按钮区域

开关和删除按钮:

        trailing: Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Switch(
              value: reminder.isEnabled,
              onChanged: (_) => provider.toggleReminder(reminder.id),
              activeColor: Colors.orange,
            ),
            IconButton(
              icon: const Icon(Icons.delete, color: Colors.red),
              onPressed: () => _showDeleteDialog(context, reminder, provider),
            ),
          ],
        ),
        isThreeLine: true,
      ),
    );
  }

Switch控制提醒的启用状态。
删除按钮点击弹出确认对话框。


类型颜色映射

不同类型用不同颜色:

  Color _getTypeColor(ReminderType type) {
    switch (type) {
      case ReminderType.feeding: return Colors.green;
      case ReminderType.medication: return Colors.orange;
      case ReminderType.vaccination: return Colors.blue;
      case ReminderType.deworming: return Colors.teal;
      case ReminderType.grooming: return Colors.pink;
      case ReminderType.veterinary: return Colors.red;
      case ReminderType.other: return Colors.grey;
    }
  }

喂食用绿色,用药用橙色,疫苗用蓝色。
颜色区分让用户快速识别类型。


类型图标映射

不同类型用不同图标:

  IconData _getTypeIcon(ReminderType type) {
    switch (type) {
      case ReminderType.feeding: return Icons.restaurant;
      case ReminderType.medication: return Icons.medication;
      case ReminderType.vaccination: return Icons.vaccines;
      case ReminderType.deworming: return Icons.bug_report;
      case ReminderType.grooming: return Icons.content_cut;
      case ReminderType.veterinary: return Icons.local_hospital;
      case ReminderType.other: return Icons.alarm;
    }
  }

图标让类型更直观。
Material Icons提供了丰富的选择。


删除确认对话框

弹出确认删除的对话框:

  void _showDeleteDialog(BuildContext context, ReminderModel reminder, ReminderProvider provider) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('确认删除'),
        content: Text('确定要删除提醒"${reminder.title}"吗?'),
        actions: [
          TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
          TextButton(
            onPressed: () {
              provider.deleteReminder(reminder.id);
              Navigator.pop(context);
            },
            child: const Text('删除', style: TextStyle(color: Colors.red)),
          ),
        ],
      ),
    );
  }
}

删除是危险操作,需要确认。
删除按钮用红色强调。


Switch开关

控制提醒启用状态:

Switch(
  value: reminder.isEnabled,
  onChanged: (_) => provider.toggleReminder(reminder.id),
  activeColor: Colors.orange,
)

value是当前状态。
onChanged调用Provider切换状态。


TextDecoration删除线

禁用状态的视觉效果:

TextStyle(
  decoration: reminder.isEnabled ? null : TextDecoration.lineThrough,
  color: reminder.isEnabled ? null : Colors.grey,
)

lineThrough添加删除线效果。
灰色文字表示禁用状态。


isThreeLine属性

ListTile的三行模式:

ListTile(
  ...
  isThreeLine: true,
)

当subtitle有多行内容时使用。
让ListTile有足够的高度。


Row的mainAxisSize

控制Row的宽度:

Row(
  mainAxisSize: MainAxisSize.min,
  children: [...],
)

MainAxisSize.min让Row宽度自适应内容。
不会占据整个trailing区域。


条件渲染

只在有数据时显示分组:

if (todayReminders.isNotEmpty) ...[
  Text('今日提醒', ...),
  SizedBox(height: 8.h),
  ...todayReminders.map((r) => _buildReminderCard(...)),
  SizedBox(height: 16.h),
],

展开运算符…让条件渲染更简洁。
没有今日提醒时这部分不会渲染。


AlertDialog使用

确认对话框的结构:

AlertDialog(
  title: const Text('确认删除'),
  content: Text('确定要删除提醒"${reminder.title}"吗?'),
  actions: [
    TextButton(...),  // 取消按钮
    TextButton(...),  // 删除按钮
  ],
)

title是对话框标题。
actions是底部的操作按钮。


小结

提醒列表页面涉及的知识点:

  • 分类展示数据
  • Switch开关控制
  • AlertDialog确认对话框
  • 条件渲染和状态样式

这些技巧在其他管理类页面也能复用。


欢迎加入OpenHarmony跨平台开发社区,一起交流Flutter开发经验:

https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐