| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- class BirthdayDatePicker extends StatefulWidget {
- final DateTime initialDate;
- final DateTime minimumDate;
- final DateTime maximumDate;
- final void Function(DateTime) onDateChanged;
- const BirthdayDatePicker({
- super.key,
- required this.initialDate,
- required this.minimumDate,
- required this.maximumDate,
- required this.onDateChanged,
- });
- @override
- State<BirthdayDatePicker> createState() => _BirthdayDatePickerState();
- }
- class _BirthdayDatePickerState extends State<BirthdayDatePicker> {
- late int selectedYear;
- late int selectedMonth;
- late int selectedDay;
- @override
- void initState() {
- super.initState();
- selectedYear = widget.initialDate.year;
- selectedMonth = widget.initialDate.month;
- selectedDay = widget.initialDate.day;
- }
- @override
- Widget build(BuildContext context) {
- return Container(
- height: 150.h,
- child: Stack(
- children: [
- Positioned(
- bottom: 57.h, // Position at the bottom
- left: 0,
- right: 0,
- top: 57.h,
- child: Container(
- height: 36.h,
- decoration: BoxDecoration(
- color: Colors.white.withValues(alpha: 0.6), // Background color
- borderRadius: BorderRadius.circular(14.r),
- ),
- ),
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- _buildPickerBuilder(
- count: widget.maximumDate.year - widget.minimumDate.year + 1,
- initialIndex: selectedYear - widget.minimumDate.year,
- itemBuilder: (index) => '${widget.minimumDate.year + index}年',
- onSelectedItemChanged: (index) {
- setState(() {
- selectedYear = widget.minimumDate.year + index;
- _adjustMonthAndDay();
- _notify();
- });
- },
- ),
- _buildPickerBuilder(
- count: _getMaxMonth(),
- initialIndex: selectedMonth - 1,
- itemBuilder: (index) => '${index + 1}月',
- onSelectedItemChanged: (index) {
- setState(() {
- selectedMonth = index + 1;
- _adjustDayForMonth();
- _notify();
- });
- },
- ),
- _buildPickerBuilder(
- count: _getMaxDay(),
- initialIndex: selectedDay - 1,
- itemBuilder: (index) => '${index + 1}日',
- onSelectedItemChanged: (index) {
- setState(() {
- selectedDay = index + 1;
- _notify();
- });
- },
- ),
- ],
- ),
- // Positioned Stack item (will be at the bottom of the Row)
- ],
- ),
- );
- }
- Widget _buildPickerBuilder({
- required int count,
- required int initialIndex,
- required String Function(int) itemBuilder,
- required Function(int) onSelectedItemChanged,
- }) {
- return Expanded(
- child: ListWheelScrollView.useDelegate(
- controller: FixedExtentScrollController(initialItem: initialIndex),
- itemExtent: 36.h,
- onSelectedItemChanged: onSelectedItemChanged,
- overAndUnderCenterOpacity: 0.35,
- childDelegate: ListWheelChildBuilderDelegate(
- builder: (context, index) {
- // 判断选中项
- bool isSelected = index == initialIndex;
- return Container(
- alignment: Alignment.center,
- color: Colors.transparent,
- child: Text(
- itemBuilder(index),
- style: TextStyle(
- fontSize: 16.sp,
- fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
- color: isSelected ? Colors.black : Colors.black,
- ),
- ),
- );
- },
- childCount: count,
- ),
- ),
- );
- }
- void _adjustMonthAndDay() {
- if (selectedYear == widget.maximumDate.year &&
- selectedMonth > widget.maximumDate.month) {
- selectedMonth = widget.maximumDate.month;
- }
- _adjustDayForMonth();
- }
- void _adjustDayForMonth() {
- int maxDay = _getMaxDay();
- if (selectedDay > maxDay) {
- selectedDay = maxDay;
- }
- }
- int _getMaxMonth() {
- if (selectedYear == widget.maximumDate.year) {
- return widget.maximumDate.month;
- }
- return 12;
- }
- int _getMaxDay() {
- if (selectedYear == widget.maximumDate.year &&
- selectedMonth == widget.maximumDate.month) {
- return widget.maximumDate.day;
- }
- return _getDaysInMonth(selectedYear, selectedMonth);
- }
- int _getDaysInMonth(int year, int month) {
- switch (month) {
- case 2:
- if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
- return 29;
- }
- return 28;
- case 4:
- case 6:
- case 9:
- case 11:
- return 30;
- default:
- return 31;
- }
- }
- void _notify() {
- final selectedDate = DateTime(selectedYear, selectedMonth, selectedDay);
- widget.onDateChanged(selectedDate);
- }
- }
|