一、整体功能概述
在许多应用中(如时间追踪、任务管理、统计报表等),用户需要筛选特定时间段的数据。
这个组件体系提供了:
-
可折叠的筛选面板;
-
快捷预设日期(本周、本月、上月、最近 X 天);
-
自定义起止日期选择;
-
国际化支持;
-
Bloc 状态管理集成。
整个功能可以用一句话概括:
“一个轻量、通用、可扩展的日期范围筛选控件”
⚙️ 二、核心模块结构
组件体系包含三个核心模块:
| 模块名 | 作用 | 文件来源 |
|---|---|---|
DateRangeTile | 主 UI 组件,展示和处理日期选择 | date_range_tile.dart |
FilterPreset | 定义快捷日期范围逻辑 | filter_preset.dart |
CloneTime | 扩展 DateTime 的克隆能力 | clone_time.dart |
下面我们逐个分析👇
🧩 三、DateRangeTile — UI 控件主体
🧠 功能简介
这是整个日期筛选功能的视觉与交互核心。
-
采用
ExpansionTile实现可折叠结构; -
展示一组
ActionChip作为快捷筛选; -
两个
ListTile负责手动选择“起始日期”和“结束日期”; -
支持清除、国际化、Bloc 默认配置。
📜 逻辑流程
graph TD
A[展开筛选面板] --> B[选择快捷预设]
A --> C[手动选择起始日期]
A --> D[手动选择结束日期]
B --> E[更新 startDate/endDate 回调]
C --> E
D --> E
E --> F[父组件通过 onStartChosen/onEndChosen 更新状态]
🧩 核心结构解析
return ExpansionTile(
title: Text(L10N.of(context).tr.filter, ...),
initiallyExpanded: initiallyExpanded,
children: [
_buildFilterPresets(), // 快捷预设
_buildStartDateTile(), // 起始日期
_buildEndDateTile(), // 结束日期
],
);
-
ExpansionTile:负责折叠结构与标题; -
FilterPreset:生成一行ActionChip; -
ListTile:展示当前起止日期和清除按钮。
⏰ 日期选择逻辑
使用 flutter_datetime_picker_plus 代替系统默认的 showDatePicker:
await dt.DatePicker.showDatePicker(
context,
currentTime: startDate,
onConfirm: (dt) => onStartChosen(DateTime(dt.year, dt.month, dt.day)),
onCancel: () => onStartChosen(oldStartDate),
theme: dt.DatePickerTheme(...),
);
✅ 这种方式允许自定义主题色、取消样式,UI 更统一。
🧹 知识点
-
自动补齐时间精度:
-
起始日期设为
00:00:00 -
结束日期设为
23:59:59.999
-
-
支持清除按钮:
-
用户可点击圆形减号图标清空选中日期;
-
-
支持国际化:
-
所有文字通过
L10N.of(context).tr.xxx获取;
-
-
默认展开控制:
-
通过
initiallyExpanded决定折叠状态。
-
🔢 四、FilterPreset — 日期范围枚举逻辑
🧠 功能说明
这是日期预设的逻辑层定义,用于提供几种常用的时间段选项:
enum FilterPreset {
thisWeek,
thisMonth,
lastMonth,
lastXDays;
}
这些选项会被映射为 ActionChip 按钮。
📅 核心逻辑分析
1️⃣ 获取起始时间
DateTime getStartDate(int firstDayOfWeekIndex, int defaultFilterDays)
不同选项对应不同算法:
-
thisWeek:计算本周第一天(考虑周起始日差异);
-
thisMonth:返回当月第一天;
-
lastMonth:返回上月第一天;
-
lastXDays:返回最近 X 天的起点。
🔍 注意:
firstDayOfWeekIndex来源于MaterialLocalizations,可自动适配区域(例如周一或周日为一周起点)。
2️⃣ 获取结束时间
DateTime? getEndDate()
部分选项返回 null(表示截止到当前时间),部分返回上月末/本月末:
-
thisWeek、lastXDays→null -
thisMonth→ 下月第一天减一秒 -
lastMonth→ 本月第一天减一秒
3️⃣ 获取展示文案
String display(BuildContext context, int defaultFilterDays)
通过 L10N 国际化资源动态显示:
-
This Week / 本周
-
This Month / 本月
-
Last Month / 上月
-
Last X Days / 最近 N 天(动态填充
N)
🧩 五、CloneTime — DateTime 扩展工具
🧠 功能说明
DateTime 本身是不可变对象,但在日期选择中有时需要复制一个旧值做恢复用。
CloneTime 扩展提供一个简洁方法:
extension CloneTime on DateTime {
DateTime clone() => DateTime(year, month, day, hour, minute, second, millisecond, microsecond);
}
✅ 用于在取消日期选择时恢复原始状态,例如:
final oldStartDate = startDate?.clone();
🔁 六、完整逻辑执行顺序
| 步骤 | 动作 | 结果 |
|---|---|---|
| 1 | 用户展开组件 | 显示快捷预设和日期选择 |
| 2 | 点击快捷预设 | 自动计算起止时间并更新状态 |
| 3 | 点击起始日期 | 弹出日期选择器(保存 oldStartDate) |
| 4 | 确认选择 | 回调更新父组件的 startDate |
| 5 | 取消选择 | 恢复 oldStartDate |
| 6 | 点击结束日期 | 同上,补齐到 23:59:59.999 |
| 7 | 点击清除图标 | 将日期设为 null |
🎨 七、视觉与交互细节
| 元素 | 用途 | 组件 |
|---|---|---|
| 过滤标题 | 展示“Filter”字样 | Text |
| 快捷预设 | 横向滑动选择 | SingleChildScrollView + Row + ActionChip |
| 日期项 | 显示当前日期或 "--" | ListTile |
| 清除按钮 | 清空日期 | IconButton |
| 日期选择弹窗 | 选中日期 | flutter_datetime_picker_plus |
💡
🧭 八、总结(Conclusion)
-
结构清晰:UI、逻辑、工具分层;
-
可配置性强:支持 Bloc、国际化、多种预设;
-
体验友好:清除、取消、补齐时间、横向滑动;
-
易扩展:添加更多预设、约束或样式都很方便。
1810

被折叠的 条评论
为什么被折叠?



