
需求
- 支持选择开始时间、结束时间
- 支持多选星期
- 选择的结束时间不能比开始时间小
- 时间列表滚桶(车轮)式转动
import 'package:flutter/material.dart';
class CustomDateTimePicker extends StatefulWidget {
const CustomDateTimePicker({super.key});
@override
_CustomDateTimePickerState createState() => _CustomDateTimePickerState();
}
class _CustomDateTimePickerState extends State<CustomDateTimePicker> {
DateTime _startTime = DateTime.now();
DateTime _endTime = DateTime.now();
final List<bool> _selectedDays = List.generate(7, (index) => false);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Text("开始时间"),
_buildTimePicker(true),
],
),
Column(
children: [
Text("结束时间"),
_buildTimePicker(false),
],
),
],
),
SizedBox(height: 20),
Text("选择星期"),
Wrap(
children: List.generate(
7,
(index) => ElevatedButton(
onPressed: () {
setState(() {
_selectedDays[index] = !_selectedDays[index];
});
},
style: ElevatedButton.styleFrom(
primary: _selectedDays[index] ? Colors.blue : Colors.grey,
),
child: Text(
_getDayAbbreviation(index),
),
),
),
),
SizedBox(height: 20),
Text("选择的时间: ${_formatTime(_startTime)} - ${_formatTime(_endTime)}"),
Text("选择的星期: ${_getSelectedDays()}"),
],
),
);
}
Widget _buildTimePicker(bool isStartTime) {
DateTime selectedTime = isStartTime ? _startTime : _endTime;
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_buildWheelPicker(selectedTime.hour, 24, (value) {
setState(() {
if (isStartTime) {
_startTime = DateTime(
_startTime.year,
_startTime.month,
_startTime.day,
value,
_startTime.minute,
);
} else {
_endTime = DateTime(
_endTime.year,
_endTime.month,
_endTime.day,
value,
_endTime.minute,
);
}
if (_endTime.isBefore(_startTime)) {
print("选择的时间不对");
}
});
}),
const Text(":", style: TextStyle(fontSize: 18, color: Colors.blue)),
_buildWheelPicker(selectedTime.minute, 60, (value) {
setState(() {
if (isStartTime) {
_startTime = DateTime(
_startTime.year,
_startTime.month,
_startTime.day,
_startTime.hour,
value,
);
} else {
_endTime = DateTime(
_endTime.year,
_endTime.month,
_endTime.day,
_endTime.hour,
value,
);
}
if (_endTime.isBefore(_startTime)) {
print("选择的时间不对");
}
});
}),
],
);
}
Widget _buildWheelPicker(int value, int maxValue, ValueChanged<int> onChanged) {
return SizedBox(
width: 50,
height: 120,
child: ListWheelScrollView(
itemExtent: 40,
squeeze: 1,
physics: const FixedExtentScrollPhysics(),
perspective: 0.007,
diameterRatio: 1.5,
offAxisFraction: 0,
useMagnifier: true,
magnification: 1.5,
onSelectedItemChanged: (index) {
onChanged(index);
},
controller: FixedExtentScrollController(initialItem: value),
children: List.generate(
maxValue,
(index) => Center(
child: Text(
index.toString().padLeft(2, '0'),
style: TextStyle(
fontSize: 18,
color: index == value ? Colors.blue : Colors.grey,
),
),
),
),
),
);
}
String _getDayAbbreviation(int index) {
return ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][index];
}
String _formatTime(DateTime time) {
return "${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
}
String _getSelectedDays() {
List<String> selectedDays = [];
for (int i = 0; i < _selectedDays.length; i++) {
if (_selectedDays[i]) {
selectedDays.add(_getDayAbbreviation(i));
}
}
return selectedDays.join(", ");
}
}