年月日选择器

import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';

import '../../../components/config/config.dart';

class MyDatePicker extends StatefulWidget {
  const MyDatePicker({
    super.key,
    this.selectedDate,
    this.startDate,
    this.endDate,
    this.onSelYear,
    this.onSelMonth,
    this.width = 280,
    this.height = 220,
  });

  final DateTime? selectedDate;
  final DateTime? startDate;
  final DateTime? endDate;
  final Function? onSelYear;
  final Function? onSelMonth;
  final double? width;
  final double? height;

  @override
  State<MyDatePicker> createState() => _MyDatePickerState();
}

class _MyDatePickerState extends State<MyDatePicker> {
  MenuController menuAnchorController = MenuController();
  FocusNode buttonFocusNode = FocusNode();

  late DateTime startDate;
  late DateTime endDate;
  late DateTime selectedDate;

  List<String> yearList = []; // 年数组
  List<String> monthList = []; // 月数组

  int yearIndex = 0; // 年的索引
  int monthIndex = 0; // 月的索引

  int curYearIndex = 0; // 年的索引
  int curMonthIndex = 0; // 月的索引

  int yearMonthPicker = 1;

  late ScrollController listviewController;

  List<String> getMonthList(int selectYear) {
    List<String> monthList = [];
    if (selectYear == startDate.year) {
      for (int i = startDate.month; i <= 12; i++) {
        monthList.add(i.toString());
      }
    } else if (selectYear == endDate.year) {
      for (int i = 1; i <= endDate.month; i++) {
        monthList.add(i.toString());
      }
    } else {
      for (int i = 1; i <= 12; i++) {
        monthList.add(i.toString());
      }
    }

    return monthList;
  }

  void initData() {
    // 初始化年份数
    for (int i = startDate.year; i <= endDate.year; i++) {
      yearList.add(i.toString());
    }
    int selectYear = selectedDate.year;
    // 选中年的月列表
    monthList = getMonthList(selectYear);
    // 去重
    final List uniqueYearList = Set.from(yearList).toList();
    final List uniqueMonthList = Set.from(monthList).toList();
    // 获取索引
    setState(() {
      yearIndex = uniqueYearList.indexOf("${selectedDate.year}");
      curYearIndex = uniqueYearList.indexOf('${DateTime.now().year}');
      monthIndex = uniqueMonthList.indexOf("${selectedDate.month}");
      curMonthIndex = uniqueMonthList.indexOf('${DateTime.now().month}');
    });

    listviewController =
        ScrollController(initialScrollOffset: yearIndex ~/ 3 * 50 - 50);
  }

  bool isFuture(int year, int month) {
    var now = DateTime.now();

    return year > now.year || (year == now.year && month >= now.month);
  }

  TextStyle getMonthStyle(bool sel, int year, int month) {
    return TextStyle(
      color: sel
          ? Colors.white
          : isFuture(year, month)
              ? textColor(context.isDarkMode)
              : labelColor(context.isDarkMode),
      fontSize: textSizeConfig.contentTextSize,
    );
  }

  @override
  void initState() {
    super.initState();
    startDate = widget.startDate ?? DateTime(1970, 10, 1);
    endDate = widget.endDate ?? DateTime(2099, 5, 15);
    selectedDate = widget.selectedDate ?? DateTime.now();
    // difference函数是Dart中日期时间类型(DateTime)的一个方法,用于计算两个日期时间之间的差值。它返回一个Duration对象,表示两个日期时间之间的时间间隔。
    if (endDate.difference(startDate).inSeconds < 0) {
      endDate = startDate;
    }
    if (selectedDate.difference(startDate).inSeconds < 0) {
      selectedDate = startDate;
    }
    if (selectedDate.difference(endDate).inSeconds > 0) {
      selectedDate = endDate;
    }
    initData();
  }

  @override
  void dispose() {
    listviewController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final List<Widget> contentWidget = [
      Container(
        padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
        decoration: BoxDecoration(
          border: Border(
            top: BorderSide(
              width: 1.5,
              color: borderColor(context.isDarkMode),
            ),
          ),
        ),
        child: Builder(builder: (context) {
          double itemheight = (widget.width! - 50) / 75 * 12 + 15;
          int curRows = curYearIndex ~/ 3;
          ScrollController gridviewController = ScrollController(
              initialScrollOffset: (curRows - 1) * itemheight + 10);
          return GridView.builder(
              controller: gridviewController,
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  mainAxisSpacing: 15,
                  crossAxisSpacing: 10,
                  childAspectRatio: 25 / 12),
              itemCount: yearList.length,
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () {
                    var oldMonth = monthList[monthIndex];
                    setState(() {
                      yearIndex = index;
                      if (yearMonthPicker == 1) {
                        yearMonthPicker = 0;
                      } else {
                        yearMonthPicker = 1;
                      }

                      updateMonthList();
                      monthIndex = monthList.indexOf(oldMonth);
                    });
                    if (widget.onSelYear != null) {
                      widget.onSelYear!(yearList[yearIndex]);
                    }
                  },
                  child: Container(
                    width: 70,
                    height: 35,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                      borderRadius: const BorderRadius.all(Radius.circular(20)),
                      border: index == curYearIndex
                          ? Border.all(
                              width: 1, color: okMarkColor(context.isDarkMode))
                          : null,
                    ),
                    child: Text(
                      yearList[index],
                      style: TextStyle(
                          fontSize: textSizeConfig.contentTextSize,
                          color: textColor(context.isDarkMode)),
                    ),
                  ),
                );
              });
        }),
      ),
      Padding(
        padding: const EdgeInsets.fromLTRB(10, 10, 10, 20),
        child: Wrap(
          spacing: 10,
          runSpacing: 10,
          alignment: WrapAlignment.start,
          children: monthList
              .map((e) => Container(
                    width: 45,
                    height: 34,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                      color: monthList.indexOf(e) == monthIndex
                          ? const Color.fromRGBO(68, 78, 238, 1)
                          : Colors.transparent,
                      borderRadius: const BorderRadius.all(Radius.circular(17)),
                      border: yearIndex == curYearIndex &&
                              monthList.indexOf(e) == curMonthIndex
                          ? Border.all(
                              width: 1, color: okMarkColor(context.isDarkMode))
                          : null,
                    ),
                    child: InkWell(
                      onTap: () {
                        setState(() {
                          monthIndex = monthList.indexOf(e);
                        });
                        if (widget.onSelYear != null) {
                          widget.onSelYear!(yearList[yearIndex]);
                        }
                        if (widget.onSelMonth != null) {
                          widget.onSelMonth!(monthList[monthIndex]);
                        }
                        SmartDialog.dismiss();
                      },
                      child: Text('$e月',
                          style: getMonthStyle(
                            monthList.indexOf(e) == monthIndex,
                            int.parse(yearList[yearIndex]),
                            int.parse(e),
                          )),
                    ),
                  ))
              .toList(),
        ),
      )
    ];
    return Column(
      children: [
        // controll层
        Container(
          width: double.infinity,
          height: 40,
          padding: const EdgeInsets.only(left: 20, right: 20),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              GestureDetector(
                onTap: () {
                  setState(() {
                    if (yearIndex > 0) {
                      yearIndex--;
                    }
                    updateMonthList();
                  });
                  if (widget.onSelYear != null) {
                    widget.onSelYear!(yearList[yearIndex]);
                  }
                },
                child: Icon(
                  Icons.chevron_left,
                  size: 24,
                  color: labelColor(context.isDarkMode),
                ),
              ),
              const Spacer(),
              GestureDetector(
                onTap: () {
                  setState(() {
                    if (yearMonthPicker == 1) {
                      yearMonthPicker = 0;
                    } else {
                      yearMonthPicker = 1;
                    }
                  });
                },
                child: Text(
                  '${yearList[yearIndex]}年',
                  style: TextStyle(
                      color: labelColor(context.isDarkMode),
                      fontSize: textSizeConfig.contentTextSize,
                      fontWeight: FontWeight.w500),
                ),
              ),
              const Spacer(),
              GestureDetector(
                onTap: () {
                  setState(() {
                    if (yearIndex < yearList.length - 1) {
                      yearIndex++;
                    }
                    updateMonthList();
                  });
                  if (widget.onSelYear != null) {
                    widget.onSelYear!(yearList[yearIndex]);
                  }
                },
                child: Icon(
                  Icons.chevron_right,
                  size: 24,
                  color: labelColor(context.isDarkMode),
                ),
              )
            ],
          ),
        ),
        Expanded(child: contentWidget[yearMonthPicker])
      ],
    );
  }

  void updateMonthList() {
    monthList = getMonthList(int.parse(yearList[yearIndex]));
    if (monthIndex > monthList.length) {
      monthIndex = monthList.length - 1;
      if (widget.onSelMonth != null) {
        widget.onSelMonth!(monthList[monthIndex]);
      }
    }
  }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值