import 'package:flutter/material.dart'; /// 自定义时间选择器对话框 /// 用于选择小时和分钟,不会自动切换选择模式 class CustomTimePickerDialog extends StatefulWidget { final String title; final TimeOfDay initialTime; const CustomTimePickerDialog({ super.key, required this.title, required this.initialTime, }); @override State createState() => _CustomTimePickerDialogState(); /// 显示时间选择器对话框 static Future show({ required BuildContext context, required String title, required TimeOfDay initialTime, }) async { return await showDialog( context: context, builder: (context) => CustomTimePickerDialog( title: title, initialTime: initialTime, ), ); } } class _CustomTimePickerDialogState extends State { late int _hours; late int _minutes; @override void initState() { super.initState(); _hours = widget.initialTime.hour; _minutes = widget.initialTime.minute; } @override Widget build(BuildContext context) { final theme = Theme.of(context); return AlertDialog( title: Text(widget.title), content: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ // 小时选择 Column( children: [ Text('小时', style: theme.textTheme.bodySmall), const SizedBox(height: 8), Row( children: [ IconButton( icon: const Icon(Icons.remove_circle_outline), onPressed: () { setState(() { if (_hours > 0) { _hours--; } else { _hours = 23; } }); }, ), Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: theme.colorScheme.primaryContainer.withOpacity(0.3), borderRadius: BorderRadius.circular(8), ), child: Text( '$_hours', textAlign: TextAlign.center, style: theme.textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), ), IconButton( icon: const Icon(Icons.add_circle_outline), onPressed: () { setState(() { if (_hours < 23) { _hours++; } else { _hours = 0; } }); }, ), ], ), ], ), const SizedBox(width: 24), // 分隔符 Text( ':', style: theme.textTheme.headlineLarge?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(width: 24), // 分钟选择 Column( children: [ Text('分钟', style: theme.textTheme.bodySmall), const SizedBox(height: 8), Row( children: [ IconButton( icon: const Icon(Icons.remove_circle_outline), onPressed: () { setState(() { if (_minutes >= 15) { _minutes -= 15; } else if (_minutes > 0) { _minutes = 0; } else { _minutes = 45; } }); }, ), Container( width: 60, padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: theme.colorScheme.secondaryContainer.withOpacity(0.3), borderRadius: BorderRadius.circular(8), ), child: Text( _minutes.toString().padLeft(2, '0'), textAlign: TextAlign.center, style: theme.textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), ), IconButton( icon: const Icon(Icons.add_circle_outline), onPressed: () { setState(() { _minutes += 15; if (_minutes >= 60) { _minutes = 0; } }); }, ), ], ), ], ), ], ), const SizedBox(height: 16), // 快速选择按钮 Wrap( spacing: 8, runSpacing: 8, alignment: WrapAlignment.center, children: [ _buildQuickTimeButton(context, theme, '00:00', 0, 0), _buildQuickTimeButton(context, theme, '08:00', 8, 0), _buildQuickTimeButton(context, theme, '12:00', 12, 0), _buildQuickTimeButton(context, theme, '18:00', 18, 0), _buildQuickTimeButton(context, theme, '20:00', 20, 0), _buildQuickTimeButton(context, theme, '22:00', 22, 0), ], ), ], ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('取消'), ), ElevatedButton( onPressed: () { Navigator.of(context).pop( TimeOfDay(hour: _hours, minute: _minutes), ); }, child: const Text('确定'), ), ], ); } Widget _buildQuickTimeButton( BuildContext context, ThemeData theme, String label, int hours, int minutes, ) { final isSelected = _hours == hours && _minutes == minutes; return OutlinedButton( onPressed: () { setState(() { _hours = hours; _minutes = minutes; }); }, style: OutlinedButton.styleFrom( backgroundColor: isSelected ? theme.colorScheme.primaryContainer.withOpacity(0.3) : null, side: BorderSide( color: isSelected ? theme.colorScheme.primary : theme.colorScheme.outline.withOpacity(0.5), width: isSelected ? 2 : 1, ), ), child: Text( label, style: TextStyle( fontSize: 12, color: isSelected ? theme.colorScheme.primary : theme.colorScheme.onSurface, ), ), ); } }