import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; /// 通用日期选择器组件 /// 支持功能: /// - 初始日期设置 /// - 日期范围限制 /// - 自定义日期格式 /// - 主题适配 /// - 空值处理 /// - 验证支持 class DatePickerField extends StatefulWidget { final DateTime? initialDate; final DateTime? firstDate; final DateTime? lastDate; final ValueChanged onDateSelected; final String labelText; final String? hintText; final bool isRequired; final TextStyle? textStyle; final InputDecoration? decoration; final DateFormat? dateFormat; final bool allowClear; final bool autoValidate; const DatePickerField({ super.key, this.initialDate, this.firstDate, this.lastDate, required this.onDateSelected, this.labelText = '选择日期', this.hintText, this.isRequired = false, this.textStyle, this.decoration, this.dateFormat, this.allowClear = true, this.autoValidate = false, }); @override State createState() => _DatePickerFieldState(); } class _DatePickerFieldState extends State { late final TextEditingController _controller; DateTime? _selectedDate; final DateFormat _defaultFormat = DateFormat('yyyy-MM-dd'); @override void initState() { super.initState(); _selectedDate = widget.initialDate; _controller = TextEditingController( text: _selectedDate != null ? _getFormattedDate(_selectedDate!) : '', ); } @override void didUpdateWidget(covariant DatePickerField oldWidget) { if (widget.initialDate != oldWidget.initialDate) { _updateDate(widget.initialDate); } super.didUpdateWidget(oldWidget); } String _getFormattedDate(DateTime date) { return (widget.dateFormat ?? _defaultFormat).format(date); } void _updateDate(DateTime? newDate) { setState(() { _selectedDate = newDate; _controller.text = newDate != null ? _getFormattedDate(newDate) : ''; }); widget.onDateSelected(newDate); } Future _selectDate() async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedDate ?? DateTime.now(), firstDate: widget.firstDate ?? DateTime(1900), lastDate: widget.lastDate ?? DateTime(2100), builder: (context, child) { return Theme( data: Theme.of(context).copyWith( colorScheme: ColorScheme.light( primary: Theme.of(context).primaryColor, ), ), child: child!, ); }, ); if (picked != null && picked != _selectedDate) { _updateDate(picked); } } void _clearDate() { _updateDate(null); } String? _validateDate(String? value) { if (widget.isRequired && _selectedDate == null) { return '请选择日期'; } return null; } @override Widget build(BuildContext context) { return TextFormField( controller: _controller, readOnly: true, style: widget.textStyle ?? Theme.of(context).textTheme.bodyMedium, decoration: (widget.decoration ?? InputDecoration( labelText: widget.labelText, hintText: widget.hintText, suffixIcon: _buildSuffixIcon(), )).copyWith( errorStyle: const TextStyle(height: 0.7), ), onTap: _selectDate, validator: widget.autoValidate ? _validateDate : null, ); } Widget _buildSuffixIcon() { return Row( mainAxisSize: MainAxisSize.min, children: [ if (widget.allowClear && _selectedDate != null) IconButton( icon: const Icon(Icons.clear, size: 18), onPressed: _clearDate, ), const Padding( padding: EdgeInsets.only(right: 8), child: Icon(Icons.calendar_today, size: 18), ), ], ); } @override void dispose() { _controller.dispose(); super.dispose(); } }