Files
rog_app/lib/widgets/custom_date_picker.dart

272 lines
7.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
class CustomDatePicker extends StatefulWidget {
final DateTime initialDate;
final DateTime firstDate;
final DateTime lastDate;
final String currentDateText;
CustomDatePicker({
required this.initialDate,
required this.firstDate,
required this.lastDate,
required this.currentDateText,
});
@override
_CustomDatePickerState createState() => _CustomDatePickerState();
}
class _CustomDatePickerState extends State<CustomDatePicker> {
late DateTime _selectedDate;
late int _selectedYear;
late int _selectedMonth;
late int _selectedDay;
late ScrollController _yearScrollController;
late ScrollController _monthScrollController;
late ScrollController _dayScrollController;
@override
void initState() {
super.initState();
_selectedDate = _parseDate(widget.currentDateText) ?? widget.initialDate;
_selectedYear = _selectedDate.year;
_selectedMonth = _selectedDate.month;
_selectedDay = _selectedDate.day;
_yearScrollController = ScrollController(
initialScrollOffset: (_selectedYear - widget.firstDate.year) * 70.0,
);
_monthScrollController = ScrollController(
initialScrollOffset: (_selectedMonth - 1) * 50.0,
);
_dayScrollController = ScrollController(
initialScrollOffset: (_selectedDay - 1) * 50.0,
);
WidgetsBinding.instance.addPostFrameCallback((_) {
_centerSelectedYear();
_centerSelectedMonth();
_centerSelectedDay();
});
}
void _centerSelectedYear() {
final screenWidth = MediaQuery.of(context).size.width;
final centerPosition = (_selectedYear - widget.firstDate.year) * 70.0 - (screenWidth / 2) + 35.0;
_yearScrollController.animateTo(
centerPosition,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void _centerSelectedMonth() {
final screenWidth = MediaQuery.of(context).size.width;
final centerPosition = (_selectedMonth - 1) * 50.0 - (screenWidth / 2) + 25.0;
_monthScrollController.animateTo(
centerPosition,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void _centerSelectedDay() {
final screenWidth = MediaQuery.of(context).size.width;
final centerPosition = (_selectedDay - 1) * 50.0 - (screenWidth / 2) + 25.0;
_dayScrollController.animateTo(
centerPosition,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
DateTime? _parseDate(String dateString) {
try {
return DateFormat('yyyy/MM/dd').parse(dateString);
} catch (e) {
return null;
}
}
@override
Widget build(BuildContext context) {
return Dialog(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'生年月日の選択',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
),
_buildLabeledPicker('', _buildYearPicker()),
_buildLabeledPicker('', _buildMonthPicker()),
_buildLabeledPicker('', _buildDayPicker()),
_buildActionButtons(),
],
),
);
}
Widget _buildLabeledPicker(String label, Widget picker) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
child: Text(label, style: TextStyle(fontWeight: FontWeight.bold)),
),
picker,
],
);
}
Widget _buildYearPicker() {
return Container(
height: 100,
child: ListView.builder(
controller: _yearScrollController,
scrollDirection: Axis.horizontal,
itemCount: widget.lastDate.year - widget.firstDate.year + 1,
itemBuilder: (context, index) {
final year = widget.firstDate.year + index;
return GestureDetector(
onTap: () {
setState(() {
_selectedYear = year;
_updateSelectedDate();
_centerSelectedYear();
});
},
child: Container(
width: 70,
padding: EdgeInsets.all(8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: _selectedYear == year ? Colors.blue : null,
borderRadius: BorderRadius.circular(4),
),
child: Text(
year.toString(),
style: TextStyle(
color: _selectedYear == year ? Colors.white : null,
),
),
),
);
},
),
);
}
Widget _buildMonthPicker() {
return Container(
height: 50,
child: ListView.builder(
controller: _monthScrollController,
scrollDirection: Axis.horizontal,
itemCount: 12,
itemBuilder: (context, index) {
final month = index + 1;
return GestureDetector(
onTap: () {
setState(() {
_selectedMonth = month;
_updateSelectedDate();
_centerSelectedMonth();
});
},
child: Container(
width: 50,
padding: EdgeInsets.all(8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: _selectedMonth == month ? Colors.blue : null,
borderRadius: BorderRadius.circular(4),
),
child: Text(
month.toString(),
style: TextStyle(
color: _selectedMonth == month ? Colors.white : null,
),
),
),
);
},
),
);
}
Widget _buildDayPicker() {
final daysInMonth = DateTime(_selectedYear, _selectedMonth + 1, 0).day;
return Container(
height: 50,
child: ListView.builder(
controller: _dayScrollController,
scrollDirection: Axis.horizontal,
itemCount: daysInMonth,
itemBuilder: (context, index) {
final day = index + 1;
return GestureDetector(
onTap: () {
setState(() {
_selectedDay = day;
_updateSelectedDate();
_centerSelectedDay();
});
},
child: Container(
width: 50,
padding: EdgeInsets.all(8),
alignment: Alignment.center,
decoration: BoxDecoration(
color: _selectedDay == day ? Colors.blue : null,
borderRadius: BorderRadius.circular(4),
),
child: Text(
day.toString(),
style: TextStyle(
color: _selectedDay == day ? Colors.white : null,
),
),
),
);
},
),
);
}
void _updateSelectedDate() {
final daysInMonth = DateTime(_selectedYear, _selectedMonth + 1, 0).day;
_selectedDay = _selectedDay.clamp(1, daysInMonth);
_selectedDate = DateTime(_selectedYear, _selectedMonth, _selectedDay);
}
Widget _buildActionButtons() {
return ButtonBar(
children: <Widget>[
TextButton(
child: Text('キャンセル'),
onPressed: () => Navigator.of(context).pop(),
),
TextButton(
child: Text('OK'),
onPressed: () => Navigator.of(context).pop(_selectedDate),
),
],
);
}
@override
void dispose() {
_yearScrollController.dispose();
_monthScrollController.dispose();
_dayScrollController.dispose();
super.dispose();
}
}