import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_export.dart'; import 'package:hmg_patient_app_new/theme/colors.dart'; class ScrollWheelTimePicker extends StatefulWidget { final int initialHour; final int initialMinute; final bool use24HourFormat; final ValueChanged? onTimeChanged; final double itemExtent; final double pickerHeight; final TextStyle? digitTextStyle; final TextStyle? separatorTextStyle; const ScrollWheelTimePicker({ super.key, this.initialHour = 8, this.initialMinute = 15, this.use24HourFormat = true, this.onTimeChanged, this.itemExtent = 60, this.pickerHeight = 180, this.digitTextStyle, this.separatorTextStyle, }); @override State createState() => _ScrollWheelTimePickerState(); } class _ScrollWheelTimePickerState extends State { late FixedExtentScrollController _hourController; late FixedExtentScrollController _minuteController; late int _selectedHour; late int _selectedMinute; int get _maxHour => widget.use24HourFormat ? 24 : 12; @override void initState() { super.initState(); _selectedHour = widget.initialHour; _selectedMinute = widget.initialMinute; final hourIndex = widget.use24HourFormat ? _selectedHour : (_selectedHour == 0 ? 11 : _selectedHour - 1); _hourController = FixedExtentScrollController(initialItem: hourIndex); _minuteController = FixedExtentScrollController(initialItem: _selectedMinute); } @override void dispose() { _hourController.dispose(); _minuteController.dispose(); super.dispose(); } void _notifyChange() { widget.onTimeChanged?.call(TimeOfDay(hour: _selectedHour, minute: _selectedMinute)); } TextStyle get _defaultDigitStyle => TextStyle( fontSize: 72.f, fontWeight: FontWeight.w800, color: AppColors.textColor, letterSpacing: 0, ); TextStyle get _defaultSeparatorStyle => TextStyle( fontSize: 40.f, fontWeight: FontWeight.w800, color: AppColors.textColor, letterSpacing: 0, ); @override Widget build(BuildContext context) { final digitStyle = widget.digitTextStyle ?? _defaultDigitStyle; final separatorStyle = widget.separatorTextStyle ?? _defaultSeparatorStyle; return SizedBox( height: widget.pickerHeight, child: Row( mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 150.w, child: ListWheelScrollView.useDelegate( controller: _hourController, itemExtent: widget.itemExtent, physics: const FixedExtentScrollPhysics(), perspective: 0.005, diameterRatio: 1.2, onSelectedItemChanged: (index) { setState(() { _selectedHour = widget.use24HourFormat ? index : index + 1; }); _notifyChange(); }, childDelegate: ListWheelChildBuilderDelegate( childCount: _maxHour, builder: (context, index) { final hour = widget.use24HourFormat ? index : index + 1; final isSelected = hour == _selectedHour; return Visibility( visible: isSelected, child: Center( child: AnimatedDefaultTextStyle( duration: const Duration(milliseconds: 200), style: digitStyle.copyWith( color: isSelected ? AppColors.textColor : AppColors.textColor.withValues(alpha: 0.3), ), child: Text(hour.toString().padLeft(2, '0')), ), )); }, ), ), ), Padding( padding: EdgeInsets.symmetric(horizontal: 2.w), child: Text(':', style: separatorStyle), ), SizedBox( width: 150.w, child: ListWheelScrollView.useDelegate( controller: _minuteController, itemExtent: widget.itemExtent, physics: const FixedExtentScrollPhysics(), perspective: 0.005, diameterRatio: 1.2, onSelectedItemChanged: (index) { setState(() { _selectedMinute = index; }); _notifyChange(); }, childDelegate: ListWheelChildBuilderDelegate( childCount: 60, builder: (context, index) { final isSelected = index == _selectedMinute; return Visibility( visible: isSelected, child: Center( child: AnimatedDefaultTextStyle( duration: const Duration(milliseconds: 200), style: digitStyle.copyWith( color: isSelected ? AppColors.textColor : AppColors.transparent.withValues(alpha: 0.3), ), child: Text(index.toString().padLeft(2, '0')), ), )); }, ), ), ), ], ), ); } }