OpenHarmony 与 Flutter 的完美融合:打造现代化个人财务管理应用(更新:日期范围筛选功能)(1.2.0版本)
OpenHarmony钱包应用v1.2.0新增了日期范围筛选功能,用户可通过直观的UI选择起止日期查看特定时间段内的交易记录。更新包含:1)日期选择器组件,支持月/日格式显示和快速清除;2)智能日期范围检查逻辑,确保结束日期包含完整一天;3)与现有搜索和分类筛选的无缝集成。该功能采用Flutter内置日期选择器,提供2020年至今的时间范围选择,并通过状态管理实时更新筛选结果,帮助用户更便捷地追踪
·
更新概述
v1.2.0 版本为 OpenHarmony 钱包应用增加了强大的日期范围筛选功能。用户现在可以按指定的日期范围查看交易,这对于查看特定时间段的财务情况非常有用。
核心功能更新
1. 日期范围筛选
功能说明
新增日期范围筛选功能,用户可以:
- 选择开始日期:指定查看交易的起始日期
- 选择结束日期:指定查看交易的结束日期
- 快速清除:一键清除日期筛选
- 实时更新:选择日期后立即显示结果
状态管理
class _OpenHarmonyWalletState extends State<OpenHarmonyWallet> {
// ... 其他状态变量
DateTime? _startDate; // 开始日期
DateTime? _endDate; // 结束日期
}
说明:
- 使用
DateTime?表示可选的日期 null表示未设置日期筛选
日期范围检查
/// 检查日期是否在范围内
bool _matchesDateRange(DateTime date) {
if (_startDate != null && date.isBefore(_startDate!)) {
return false;
}
if (_endDate != null) {
final endOfDay = _endDate!.add(const Duration(days: 1));
if (date.isAfter(endOfDay)) {
return false;
}
}
return true;
}
说明:
- 检查交易日期是否在开始日期之后
- 检查交易日期是否在结束日期之前
- 结束日期包含整个一天(到 23:59:59)
筛选逻辑集成
void _applyFilters() {
_filteredTransactions = _transactions.where((t) {
final matchesSearch = t.title.toLowerCase().contains(_searchQuery.toLowerCase());
final matchesCategory = _selectedCategory == null || t.category == _selectedCategory;
final matchesDateRange = _matchesDateRange(t.date);
return matchesSearch && matchesCategory && matchesDateRange;
}).toList();
}
说明:
- 日期范围筛选与搜索和分类筛选联合工作
- 交易必须同时满足所有条件
2. 日期选择器 UI
日期范围筛选组件
Widget _buildDateRangeFilter() {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(
child: _buildDatePickerButton(
label: _startDate == null ? '开始日期' : '${_startDate!.month}/${_startDate!.day}',
onTap: () => _selectStartDate(),
),
),
const SizedBox(width: 12),
Expanded(
child: _buildDatePickerButton(
label: _endDate == null ? '结束日期' : '${_endDate!.month}/${_endDate!.day}',
onTap: () => _selectEndDate(),
),
),
const SizedBox(width: 8),
if (_startDate != null || _endDate != null)
GestureDetector(
onTap: _clearDateFilter,
child: Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.red.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Icon(Icons.close, color: Colors.red, size: 20),
),
),
],
),
);
}
说明:
- 使用
Row并排显示两个日期选择按钮 - 动态显示已选择的日期(格式:月/日)
- 当有日期被选中时显示清除按钮

日期选择按钮
Widget _buildDatePickerButton({
required String label,
required VoidCallback onTap,
}) {
return GestureDetector(
onTap: onTap,
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.calendar_today, size: 16, color: Colors.blue),
const SizedBox(width: 6),
Text(
label,
style: const TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis,
),
],
),
),
);
}
说明:
- 灰色边框设计,清晰的按钮边界
- 日历图标提示用户这是日期选择
- 文字显示当前选中的日期或默认文本
日期选择器对话框
Future<void> _selectStartDate() async {
final picked = await showDatePicker(
context: context,
initialDate: _startDate ?? DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime.now(),
);
if (picked != null) {
_updateStartDate(picked);
}
}
Future<void> _selectEndDate() async {
final picked = await showDatePicker(
context: context,
initialDate: _endDate ?? DateTime.now(),
firstDate: _startDate ?? DateTime(2020),
lastDate: DateTime.now(),
);
if (picked != null) {
_updateEndDate(picked);
}
}
说明:
- 使用 Flutter 内置的
showDatePicker组件 - 开始日期范围:2020年到今天
- 结束日期范围:开始日期(如已选)到今天
- 确保结束日期不早于开始日期

3. 日期筛选更新方法
更新开始日期
void _updateStartDate(DateTime? date) {
setState(() {
_startDate = date;
_applyFilters();
});
}
更新结束日期
void _updateEndDate(DateTime? date) {
setState(() {
_endDate = date;
_applyFilters();
});
}
清除日期筛选
void _clearDateFilter() {
setState(() {
_startDate = null;
_endDate = null;
_applyFilters();
});
}
说明:
- 每次更新都会触发
_applyFilters()重新计算结果 - 清除按钮同时清除开始和结束日期
UI 变化
交易历史筛选区域的新增元素

布局结构
┌─────────────────────────────────────────┐
│ 交易历史 (标题) │
├─────────────────────────────────────────┤
│ [搜索框] 搜索交易... │
├─────────────────────────────────────────┤
│ [全部] [工资] [食物] [交通] ... │
├─────────────────────────────────────────┤
│ [开始日期] [结束日期] [清除按钮] │
├─────────────────────────────────────────┤
│ 交易项 1 │
│ 交易项 2 │
│ 交易项 3 │
└─────────────────────────────────────────┘
日期筛选栏样式
- 高度:约 44px
- 按钮宽度:各占 50% - 8px 间距
- 清除按钮:仅在有日期被选中时显示
- 颜色:灰色边框,蓝色图标
响应式设计
- 日期按钮使用
Expanded自适应宽度 - 清除按钮固定大小,不占用主要空间
- 文字自动省略号处理溢出
使用场景
场景 1:查看本月交易
- 点击"开始日期",选择 12/1
- 点击"结束日期",选择 12/31
- 显示 12 月的所有交易
场景 2:查看特定日期的交易
- 点击"开始日期",选择 12/15
- 点击"结束日期",选择 12/15
- 显示 12 月 15 日的所有交易
场景 3:联合多个筛选条件
- 搜索"午"
- 选择"食物"分类
- 选择日期范围 12/1 - 12/31
- 显示 12 月包含"午"的食物交易
场景 4:快速清除筛选
- 已设置日期筛选
- 点击清除按钮(红色 × 按钮)
- 日期筛选被清除,显示全部交易
技术实现细节
日期比较
// 检查日期是否在开始日期之后
if (_startDate != null && date.isBefore(_startDate!)) {
return false;
}
// 检查日期是否在结束日期之前(包含整天)
if (_endDate != null) {
final endOfDay = _endDate!.add(const Duration(days: 1));
if (date.isAfter(endOfDay)) {
return false;
}
}
说明:
isBefore()和isAfter()是 DateTime 的内置方法- 为了包含结束日期的整个一天,添加 1 天后进行比较
- 这样 12/15 23:59:59 的交易也会被包含
日期格式化
label: _startDate == null ? '开始日期' : '${_startDate!.month}/${_startDate!.day}'
说明:
- 简洁的 M/D 格式显示日期
- 节省按钮空间
- 用户可以通过日期选择器查看完整日期
性能考虑
筛选性能
- 每次日期变化都会重新过滤整个列表
- 对于 1000 条以内的交易记录性能良好
- 大数据量时可考虑分页或虚拟列表
日期选择器
- 使用 Flutter 内置组件,性能优化
- 日期范围限制在 2020 年到今天,避免过大范围
版本对比
| 功能 | v1.0.0 | v1.1.0 | v1.2.0 |
|---|---|---|---|
| 基础交易管理 | ✅ | ✅ | ✅ |
| 余额显示 | ✅ | ✅ | ✅ |
| 快速操作按钮 | ✅ | ✅ | ✅ |
| 分类统计 | ✅ | ✅ | ✅ |
| 搜索功能 | ❌ | ✅ | ✅ |
| 分类筛选 | ❌ | ✅ | ✅ |
| 日期范围筛选 | ❌ | ❌ | ✅ |
| 日期选择器 | ❌ | ❌ | ✅ |
| 联合多条件筛选 | ❌ | ❌ | ✅ |
下一步计划
v1.3.0 将继续优化功能,计划增加:
- 📊 数据可视化图表(柱状图、饼图)
- 💰 金额范围筛选
- 📈 月度统计报表
- ⚡ 筛选结果导出
感谢使用 OpenHarmony 钱包! 🎉
如有建议或问题,欢迎反馈。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)