Flutter打造OpenHarmony日期选择器
Flutter日期选择功能实现指南 摘要:本文介绍了Flutter中实现日期选择功能的两种主要方式。通过showDatePicker可实现单日期选择,返回DateTime对象;showDateRangePicker支持日期范围选择,返回DateTimeRange。文章详细展示了基础实现代码,包括日期格式化、验证和计算等核心功能。同时涵盖了企业级应用场景,如禁用特定日期、日期范围业务验证、本地化显示
·
案例概述
本案例展示如何使用 showDatePicker 和 showDateRangePicker 实现日期选择功能,包括单日期选择和日期范围选择。
核心概念
1. showDatePicker
- 显示日期选择对话框;
- 返回选中的
DateTime; - 支持初始日期、最小/最大日期等参数。
2. showDateRangePicker
- 显示日期范围选择对话框;
- 返回
DateTimeRange; - 包含开始日期和结束日期。
3. DateTime 操作
- 获取年月日:
date.year、date.month、date.day; - 计算日期差:
DateTime.now().difference(date).inDays。
代码详解
1. 单日期选择
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: _selectedDate ?? DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now(),
);
if (picked != null) {
setState(() {
_selectedDate = picked;
});
}
}
2. 日期范围选择
Future<void> _selectDateRange(BuildContext context) async {
final DateTimeRange? picked = await showDateRangePicker(
context: context,
firstDate: DateTime(2020),
lastDate: DateTime.now(),
);
if (picked != null) {
setState(() {
_startDate = picked.start;
_endDate = picked.end;
});
}
}
3. 日期格式化
String formatDate(DateTime date) {
return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}
高级话题:日期选择的高级应用
1. 自定义日期选择器
创建自定义的日期选择器以满足特殊需求:
class CustomDatePicker extends StatefulWidget {
State<CustomDatePicker> createState() => _CustomDatePickerState();
}
2. 日期验证
validator: (value) {
if (value == null) return '请选择日期';
if (value.isBefore(DateTime.now())) return '不能选择过去的日期';
return null;
}
3. 日期范围验证
if (_endDate.isBefore(_startDate)) {
return '结束日期不能早于开始日期';
}
4. 日期快捷选择
提供常用的日期快捷选项:
Row(
children: [
ElevatedButton(
onPressed: () => _selectDateRange(
DateTime.now().subtract(Duration(days: 7)),
DateTime.now(),
),
child: Text('最近7天'),
),
ElevatedButton(
onPressed: () => _selectDateRange(
DateTime.now().subtract(Duration(days: 30)),
DateTime.now(),
),
child: Text('最近30天'),
),
],
)
5. 日期显示格式化
final formatter = DateFormat('yyyy-MM-dd HH:mm:ss');
Text(formatter.format(_selectedDate))
6. 日期计算
// 计算年龄
int calculateAge(DateTime birthDate) {
return DateTime.now().year - birthDate.year;
}
// 计算工作天数
int calculateWorkingDays(DateTime start, DateTime end) {
int days = 0;
for (var date = start; date.isBefore(end); date = date.add(Duration(days: 1))) {
if (date.weekday < 6) days++; // 周一到周五
}
return days;
}
7. 日期范围的可视化
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.blue.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
Text('开始日期:${formatDate(_startDate)}'),
Text('结束日期:${formatDate(_endDate)}'),
Text('天数:${_endDate.difference(_startDate).inDays}'),
],
),
)
8. 日期选择的国际化
showDatePicker(
context: context,
locale: Locale('zh', 'CN'),
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime.now(),
)
9. 日期选择的性能优化
缓存日期选择器的状态,避免重复创建:
late final _datePickerState = DatePickerState();
void dispose() {
_datePickerState.dispose();
super.dispose();
}
10. 日期选择与表单集成
TextFormField(
readOnly: true,
decoration: InputDecoration(
suffixIcon: Icon(Icons.calendar_today),
),
onTap: () => _selectDate(context),
validator: (value) {
if (_selectedDate == null) return '请选择日期';
return null;
},
)
通过这些高级技巧,你可以构建出功能完整的日期选择系统。
高级话题:日期选择的企业级应用
1. 禁用特定日期
showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2020),
lastDate: DateTime.now(),
selectableDayPredicate: (DateTime date) {
// 禁用周末
if (date.weekday == 6 || date.weekday == 7) return false;
// 禁用特定日期
if (disabledDates.contains(date)) return false;
return true;
},
)
2. 日期范围的业务逻辑
bool isValidDateRange(DateTime start, DateTime end) {
if (end.isBefore(start)) return false;
if (end.difference(start).inDays > 365) return false;
return true;
}
3. 日期的本地化显示
final formatter = DateFormat('yyyy年MM月dd日', 'zh_CN');
Text(formatter.format(_selectedDate))
4. 日期的快捷选择
Row(
children: [
ElevatedButton(
onPressed: () => _selectDateRange(
DateTime.now().subtract(Duration(days: 7)),
DateTime.now(),
),
child: Text('最近7天'),
),
ElevatedButton(
onPressed: () => _selectDateRange(
DateTime.now().subtract(Duration(days: 30)),
DateTime.now(),
),
child: Text('最近30天'),
),
],
)
5. 日期的重复选择
class RecurringDate {
final DateTime startDate;
final String frequency; // 'daily', 'weekly', 'monthly'
final int? endAfter; // 重复次数
final DateTime? endDate; // 结束日期
List<DateTime> getOccurrences() {
// 计算所有重复日期
}
}
6. 日期的时区处理
final utcDate = _selectedDate.toUtc();
final localDate = utcDate.toLocal();
7. 日期的导出
String exportDateAsISO8601(DateTime date) {
return date.toIso8601String();
}
DateTime importDateFromISO8601(String dateString) {
return DateTime.parse(dateString);
}
8. 日期的比较
bool isSameDay(DateTime a, DateTime b) {
return a.year == b.year && a.month == b.month && a.day == b.day;
}
bool isToday(DateTime date) {
return isSameDay(date, DateTime.now());
}
9. 日期的缓存
Future<void> _saveDateSelection() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('selected_date', _selectedDate.toIso8601String());
}
Future<void> _loadDateSelection() async {
final prefs = await SharedPreferences.getInstance();
final dateString = prefs.getString('selected_date');
if (dateString != null) {
setState(() => _selectedDate = DateTime.parse(dateString));
}
}
10. 日期的测试
test('日期范围验证', () {
final start = DateTime(2024, 1, 1);
final end = DateTime(2024, 1, 31);
expect(isValidDateRange(start, end), true);
expect(isValidDateRange(end, start), false);
});
通过这些企业级技巧,你可以构建出功能完整的日期管理系统。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐

所有评论(0)