169 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Dart
		
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:intl/intl.dart';
 | |
| import 'package:qhd_prevention/customWidget/custom_button.dart';
 | |
| 
 | |
| class HDatePickerDialog extends StatefulWidget {
 | |
|   final DateTime initialDate;
 | |
|   final VoidCallback onCancel;
 | |
|   final ValueChanged<DateTime> 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<HDatePickerDialog> {
 | |
|   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 ? Colors.blue : 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: [
 | |
|                       Expanded(child: CustomButton(text: '取消',height: 40,backgroundColor: Colors.grey.shade500,
 | |
|                           onPressed: widget.onCancel),),
 | |
|                       SizedBox(width: 30,),
 | |
|                       Expanded(child: CustomButton(text: '确定',height: 40,backgroundColor: Colors.blue,
 | |
|                           onPressed: () => widget.onConfirm(_selectedDate)),)
 | |
| 
 | |
| 
 | |
|                     ],
 | |
|                   ),
 | |
|                 ],
 | |
|               ),
 | |
|             ),
 | |
|           ),
 | |
|         ),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |