didvan-app/lib/views/notification_time/widgets/custom_cupertino_date_picke...

336 lines
10 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../../models/day_time.dart';
import '../../../utils/date_time.dart';
class CustomCupertinoDatePicker extends StatefulWidget {
final double itemExtent;
final void Function(DayTime)
onSelectedItemChanged; // Text style of selected item
final TextStyle? selectedStyle; // Text style of unselected item
final TextStyle? unselectedStyle; // Text style of disabled item
final TextStyle? disabledStyle; // Minimum selectable date
final DayTime? selectedTime;
final bool disable;
const CustomCupertinoDatePicker({
Key? key,
required this.itemExtent,
required this.onSelectedItemChanged,
this.selectedTime,
this.selectedStyle,
this.unselectedStyle,
this.disabledStyle,
this.disable = false,
}) : super(key: key);
@override
State<CustomCupertinoDatePicker> createState() =>
_CustomCupertinoDatePickerState();
}
class _CustomCupertinoDatePickerState extends State<CustomCupertinoDatePicker> {
late DayTime selectedTime = DateTimeUtils.handleDayTime(
"${DateTime.now().hour.toString()}:${DateTime.now().minute.toString()}");
late int _selectedMeridiemIndex;
late int _selectedHourIndex;
late int _selectedMinuteIndex;
late final FixedExtentScrollController _meridiemScrollController;
late final FixedExtentScrollController _hourScrollController;
late final FixedExtentScrollController _minuteScrollController;
final _meridiem = [
'قبل از ظهر',
'بعد از ظهر',
];
final _timeH = [];
final _timeM = [];
@override
void initState() {
super.initState();
for (int i = 1; i < 12 + 1; i++) {
String twoDigitNumber = i.toString().padLeft(2, '0');
_timeH.add(twoDigitNumber);
}
for (int i = 1; i < 12 + 1; i++) {
String twoDigitNumber = i.toString().padLeft(2, '0');
_timeH.add(twoDigitNumber);
}
for (int i = 0; i < 59 + 1; i++) {
String twoDigitNumber = i.toString().padLeft(2, '0');
_timeM.add(twoDigitNumber);
}
_meridiemScrollController = FixedExtentScrollController();
_hourScrollController = FixedExtentScrollController();
_minuteScrollController = FixedExtentScrollController();
if (widget.selectedTime != null) {
selectedTime = widget.selectedTime!;
}
_initDates();
}
void _initDates() {
_selectedMeridiemIndex = 0;
switch (selectedTime.meridiem) {
case Meridiem.AM:
_selectedMeridiemIndex = 0;
_selectedHourIndex = int.parse(selectedTime.hour) - 1;
break;
case Meridiem.PM:
_selectedMeridiemIndex = 1;
_selectedHourIndex = (int.parse(selectedTime.hour) + 12) - 1;
break;
}
_selectedMinuteIndex = int.parse(selectedTime.minute);
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollList(_meridiemScrollController, _selectedMeridiemIndex);
_scrollList(_hourScrollController, _selectedHourIndex);
_scrollList(_minuteScrollController, _selectedMinuteIndex);
});
}
void _scrollList(FixedExtentScrollController controller, int index) {
controller.animateToItem(
index,
curve: Curves.easeIn,
duration: const Duration(milliseconds: 300),
);
}
@override
void dispose() {
_meridiemScrollController.dispose();
_hourScrollController.dispose();
_minuteScrollController.dispose();
super.dispose();
}
void _onSelectedItemChanged(int index, SelectorType type) {
switch (type) {
case SelectorType.meridiem:
_selectedMeridiemIndex = index; // if month is changed to february &
if (_selectedMeridiemIndex == 0) {
if (_selectedHourIndex > 12 - 1) {
_selectedHourIndex -= 12;
_hourScrollController.jumpToItem(_selectedHourIndex);
}
} else {
if (_selectedHourIndex < 12 - 1) {
_selectedHourIndex += 12;
_hourScrollController.jumpToItem(_selectedHourIndex);
}
}
if (index == 0) {
selectedTime.meridiem = Meridiem.AM;
} else {
selectedTime.meridiem = Meridiem.PM;
}
break;
case SelectorType.hour:
_selectedHourIndex = index; // if month is changed to february &
if (_selectedHourIndex > 12 - 1) {
_selectedMeridiemIndex = 1;
_meridiemScrollController.jumpToItem(_selectedMeridiemIndex);
} else {
_selectedMeridiemIndex = 0;
_meridiemScrollController.jumpToItem(_selectedMeridiemIndex);
}
selectedTime.hour = _timeH[index];
break;
case SelectorType.minute:
_selectedMinuteIndex = index;
selectedTime.minute = _timeM[index];
break;
}
setState(() {});
widget.onSelectedItemChanged(selectedTime);
}
/// check if the given day, month or year index is disabled
bool _isDisabled(int index, SelectorType type) {
// switch (type) {
// case SelectorType.meridiem:
// break;
//
// case SelectorType.hour:
// break;
//
// case SelectorType.minute:
// break;
// }
return false;
}
@override
Widget build(BuildContext context) {
Color shadow = Theme.of(context).colorScheme.background;
return IgnorePointer(
ignoring: widget.disable,
child: Stack(
children: [
Positioned.fill(
child: Center(
child: Container(
height: 64,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primary.withOpacity(widget.disable? 0.2: 1),
borderRadius: BorderRadius.circular(18)),
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 12),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(),
VerticalDivider(
color: Colors.white,
),
VerticalDivider(
color: Colors.white,
),
SizedBox(),
],
),
),
),
),
),
Row(
children: [
Expanded(child: _meridiemSelector()),
Expanded(child: _minuteSelector()),
Expanded(child: _hourSelector()),
],
),
Positioned(
top: 0,
left: 0,
right: 0,
child: Container(
height: 32,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
shadow.withOpacity(1),
shadow.withOpacity(0.9),
shadow.withOpacity(0.8),
shadow.withOpacity(0.6),
shadow.withOpacity(0.5),
shadow.withOpacity(0.4),
])),
)),
Positioned(
bottom: 0,
left: 0,
right: 0,
child: Container(
height: 32,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
colors: [
shadow.withOpacity(1),
shadow.withOpacity(0.9),
shadow.withOpacity(0.8),
shadow.withOpacity(0.6),
shadow.withOpacity(0.5),
shadow.withOpacity(0.4),
])),
)),
],
),
);
}
Widget _selector({
required List<dynamic> values,
required int selectedValueIndex,
required bool Function(int) isDisabled,
required void Function(int) onSelectedItemChanged,
required FixedExtentScrollController scrollController,
}) {
return CupertinoPicker.builder(
childCount: values.length,
itemExtent: widget.itemExtent,
scrollController: scrollController,
squeeze: 1.45,
useMagnifier: false,
diameterRatio: 2.3,
magnification: 1.0,
offAxisFraction: 0.0,
selectionOverlay: const SizedBox(),
onSelectedItemChanged: onSelectedItemChanged,
itemBuilder: (context, index) => Container(
height: widget.itemExtent,
alignment: Alignment.center,
decoration: const BoxDecoration(),
child: Text(
'${values[index]}',
style: index == selectedValueIndex
? widget.selectedStyle
: isDisabled(index)
? widget.disabledStyle
: widget.unselectedStyle,
),
),
);
}
Widget _meridiemSelector() {
return _selector(
values: _meridiem,
selectedValueIndex: _selectedMeridiemIndex,
scrollController: _meridiemScrollController,
isDisabled: (index) => _isDisabled(index, SelectorType.meridiem),
onSelectedItemChanged: (v) => _onSelectedItemChanged(
v,
SelectorType.meridiem,
),
);
}
Widget _hourSelector() {
return _selector(
values: _timeH,
selectedValueIndex: _selectedHourIndex,
scrollController: _hourScrollController,
isDisabled: (index) => _isDisabled(index, SelectorType.hour),
onSelectedItemChanged: (v) => _onSelectedItemChanged(
v,
SelectorType.hour,
),
);
}
Widget _minuteSelector() {
return _selector(
values: _timeM,
selectedValueIndex: _selectedMinuteIndex,
scrollController: _minuteScrollController,
isDisabled: (index) => _isDisabled(index, SelectorType.minute),
onSelectedItemChanged: (v) => _onSelectedItemChanged(
v,
SelectorType.minute,
),
);
}
}