import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class HDatePickerDialog extends StatefulWidget { final DateTime initialDate; final VoidCallback onCancel; final ValueChanged onConfirm; const HDatePickerDialog({ Key? key, required this.initialDate, required this.onCancel, required this.onConfirm, }) : super(key: key); @override _HDatePickerDialogState createState() => _HDatePickerDialogState(); } class _HDatePickerDialogState extends State { late DateTime _displayedMonth; late DateTime _selectedDate; @override void initState() { super.initState(); _selectedDate = widget.initialDate; _displayedMonth = DateTime(widget.initialDate.year, widget.initialDate.month); } void _prevMonth() { setState(() { _displayedMonth = DateTime(_displayedMonth.year, _displayedMonth.month - 1); }); } void _nextMonth() { setState(() { _displayedMonth = DateTime(_displayedMonth.year, _displayedMonth.month + 1); }); } @override Widget build(BuildContext context) { final daysInMonth = DateUtils.getDaysInMonth(_displayedMonth.year, _displayedMonth.month); final firstWeekday = DateTime(_displayedMonth.year, _displayedMonth.month, 1).weekday; return GestureDetector( onTap: widget.onCancel, child: Material( color: Colors.black54, child: Center( child: GestureDetector( onTap: () {}, // 拦截点击 child: Container( width: 320, padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8), ), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 顶部显示选中日期 Text( DateFormat('yyyy-MM-dd').format(_selectedDate), style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 16), // 月份选择 Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ IconButton( icon: const Icon(Icons.chevron_left), onPressed: _prevMonth, ), Text( DateFormat('yyyy 年 MM 月').format(_displayedMonth), style: const TextStyle(fontSize: 16), ), IconButton( icon: const Icon(Icons.chevron_right), onPressed: _nextMonth, ), ], ), // 星期标题 Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: ['一', '二', '三', '四', '五', '六', '日'] .map((d) => Expanded( child: Center(child: Text(d)), )) .toList(), ), SizedBox(height: 10,), // 日历网格 GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, childAspectRatio: 1.2, crossAxisSpacing: 4, mainAxisSpacing: 4, ), itemCount: daysInMonth + firstWeekday - 1, itemBuilder: (context, index) { if (index < firstWeekday - 1) { return const SizedBox(); } final day = index - firstWeekday + 2; final date = DateTime(_displayedMonth.year, _displayedMonth.month, day); final isSelected = DateUtils.isSameDay(date, _selectedDate); return GestureDetector( onTap: () { setState(() { _selectedDate = date; }); }, child: Container( decoration: BoxDecoration( color: isSelected ? Theme.of(context).primaryColor : null, shape: BoxShape.circle, ), child: Center( child: Text( '$day', style: TextStyle( color: isSelected ? Colors.white : Colors.black87, ), ), ), ), ); }, ), const SizedBox(height: 16), // 按钮 Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ TextButton( onPressed: widget.onCancel, child: const Text('取消'), ), ElevatedButton( onPressed: () => widget.onConfirm(_selectedDate), child: const Text('确定'), ), ], ), ], ), ), ), ), ), ); } }