IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> flutter 自定义日历选择(没有用到第三方日历库) -> 正文阅读

[移动开发]flutter 自定义日历选择(没有用到第三方日历库)

flutter 自定义日历选择

禁止转载、抄袭

功能需求

实现后是长这样的(因为项目要以底部弹窗显示,也可以整个UI自定义)
要代码的私信我(看人品回复)
请添加图片描述
项目需求:

  1. 星期一在第一,星期日在最后
  2. 一开始显示的是当前月份
  3. 有startTime和endTime的限制,所以并不是每个日期都能选择
  4. 选择全部工作日按钮,意思是除了星期六日和第三点的条件都选择
  5. 已选统计选了多少天,下一步把选择的传到下个页面
  6. 没有说需不需要滑动切换月份(我是没做了)
  7. 在第3点外的月份不能点击全选

干就完事了

我看了日历第三方库,有些符合要求,但有些不符合要求(淦),看了原理直接手撕算了。

实际原理就是gradeview(iOS里的collectionView),里面添数据而已,就是处理数据比较麻烦,幸好没叫我做滑动。

说这么多,上核心代码

因为部分是项目的代码,我不可能公开,你需要的话可以私信我,女的请私信你的qq(感觉不可能)

工具类

这些函数的dateTime date都是该月的第一天,其他不管用(主要是自己懒得再重新处理数据)


  ///星期一为第一天
  static int computeFirstDay(
      DateTime date, MaterialLocalizations localizations) {
    final int weekdayFromMonday = date.weekday;
    final int firstDayOfWeekFromSunday = localizations.firstDayOfWeekIndex + 1;
    final int firstDayOfWeekFromMonday = firstDayOfWeekFromSunday % 7;
    return (weekdayFromMonday - firstDayOfWeekFromMonday) % 7;
  }
  static const List<int> _daysInMonth = <int>[
    31,
    -1,
    31,
    30,
    31,
    30,
    31,
    31,
    30,
    31,
    30,
    31
  ];
  /// 获取这个月的天数
  static int getDayCountInMonth(DateTime date) {
    int month = date.month;
    int year = date.year;
    if (month == DateTime.february) {
      final bool isLeapYear =
          (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
      if (isLeapYear) return 29;
      return 28;
    }
    return _daysInMonth[month-1];
  }

这些大概是定位该月gradeView(collectionView)的显示数据位置。

UI方面的代码我不怎么想给,毕竟产品+UI都不一样

调用

List<DateModel> list = [];
  List<DateTime> returnList = [];
  List<TotalDateModel> totalList = [];
  bool isfullChoice = false;
  bool canChooseMoon = true;
@override
  void initState() {
    super.initState();
    WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      setState(() {
        list = getDateModel(MaterialLocalizations.of(context));
      });

    });
  }


class DateModel {
  int day;
  bool isChoosen;
  DateModel({
    required this.day,
    required this.isChoosen,
  });
}

创建原始数据

///创建数据
  List<DateModel> getDateModel(MaterialLocalizations localizations){
    //当月的总天数
    final int currentMonthTotalDays = CommonUtils.getMonthDay(widget.date);
    //每月的一号对应的周几(星期一在第二天)若星期一第一天就-1
    final int firstDayIsWeekInMonth = CommonUtils.computeFirstDay(widget.date, localizations);
    final List<DateModel> dayList = [];
    for(int i = 0;i < firstDayIsWeekInMonth; i++) {
      final DateModel model = DateModel(day: 0,isChoosen: false);
      dayList.add(model);
    }
    for(int i = 1; i <= currentMonthTotalDays; i ++) {
      final DateModel model = DateModel(day: i,isChoosen: false);
      dayList.add(model);
    }
    return dayList;
  }

切换月份

//切换月份处理事件 isRight为1 就+月,-1就-月
  void changeMonth(int isRight) {
    //寻找list里的元素内容,若找不到返回orelse TotalDateModel
    totalList.firstWhere((element) => element.date == widget.date, orElse: () {
      final TotalDateModel newModel = TotalDateModel(date: widget.date, dateList: list);
      totalList.add(newModel);
      return newModel;
    }).dateList = list;

    final DateTime nextDate = DateTime(widget.date.year, widget.date.month + isRight, widget.date.day);
    widget.date = nextDate;
    if(widget.goNextMonth != null) {
      widget.goNextMonth(widget.date);
    }
    list = totalList.firstWhere((element) => element.date == nextDate, orElse: () {
      list = getDateModel(MaterialLocalizations.of(context));
      final TotalDateModel newModel = TotalDateModel(dateList: list);
      return newModel;
    }).dateList;

    //是否全选
    final int firstDayIsWeekInMonth =
        CommonUtils.computeFirstDay(widget.date, MaterialLocalizations.of(context));


    isfullChoice = true;
    canChooseMoon = true;
    ///遍历date的数组,起始时间和终止时间内false
    for (int j = firstDayIsWeekInMonth; j < list.length; j++) {
      final int index = list[j].day + firstDayIsWeekInMonth;
      if(index%7 != 0 && (index + 1)%7 != 0){
        if (list[j].isChoosen == false) {
          final DateTime dateTime = DateTime(widget.date.year,widget.date.month,list[j].day);
          final epochTime = dateTime.millisecondsSinceEpoch;
          if ((widget.model.validStartDate ?? 0) <= epochTime && epochTime <= (widget.model.validEndDate ?? 0)){
            isfullChoice = false;
            break;
          }
        }
      }
    }
    ///该月份是否能点击全选
    final int startTime = DateTime(widget.date.year,widget.date.month,1).millisecondsSinceEpoch;
    final int endTime = DateTime(widget.date.year,widget.date.month,list[list.length - 1].day).millisecondsSinceEpoch;
    if((widget.model.validStartDate ?? 0) > endTime || (widget.model.validEndDate ?? 0) < startTime) {
      canChooseMoon = false;
      isfullChoice = false;
    }
    setState(() {});
  }

全选按钮

void chooseAllAction() {
    //每月的一号对应的周几(星期一在第二天)若星期一第一天就-1
    final int firstDayIsWeekInMonth = CommonUtils.computeFirstDay(widget.date, MaterialLocalizations.of(context));
    //反选
    if(isfullChoice) {
      for(int i = firstDayIsWeekInMonth;i < list.length;i++){
        if (list[i].isChoosen) {
          final int index = list[i].day + firstDayIsWeekInMonth;
          if(index%7 != 0 && (index + 1)%7 != 0){
            final DateTime dateTime = DateTime(widget.date.year,widget.date.month,list[i].day);
            final epochTime = dateTime.millisecondsSinceEpoch;
            if ((widget.model.validStartDate ?? 0) <= epochTime && epochTime <= (widget.model.validEndDate ?? 0)){
              list[i].isChoosen = false;
              returnList.remove(dateTime);
            }
          }
        }
      }
    }else {      //正选
      for(int i = firstDayIsWeekInMonth;i < list.length;i++){
        if (!list[i].isChoosen) {
          final int index = list[i].day + firstDayIsWeekInMonth;
          if(index%7 != 0 && (index + 1)%7 != 0){
            final DateTime dateTime = DateTime(widget.date.year,widget.date.month,list[i].day);
            final epochTime = dateTime.millisecondsSinceEpoch;
            if ((widget.model.validStartDate ?? 0) <= epochTime &&
                epochTime <= (widget.model.validEndDate ?? 0)){
              if (list[i].isChoosen == false) {
                returnList.add(dateTime);
              }
              list[i].isChoosen = true;
            }
          }
        }
      }
    }
    setState(() {
      isfullChoice = !isfullChoice;
    });
  }

点击单个item的处理事件

onTap: (){
              //每月的一号对应的周几(星期一在第二天)若星期一第一天就-1
              final int firstDayIsWeekInMonth = CommonUtils.computeFirstDay(widget.date, MaterialLocalizations.of(context));
              final DateTime dateTime = DateTime(widget.date.year,widget.date.month,list[i].day);
              final epochTime = dateTime.millisecondsSinceEpoch;
              if ((widget.model.validStartDate ?? 0) <= epochTime && epochTime <= (widget.model.validEndDate ?? 0)){
                list[i].isChoosen = !list[i].isChoosen;
                if(list[i].isChoosen){
                  isfullChoice = true;
                  returnList.add(dateTime);
                  for(int j = firstDayIsWeekInMonth;j < list.length;j++){
                    if(list[j].isChoosen == false) {
                      final int index = list[j].day + firstDayIsWeekInMonth;
                      if(index%7 != 0 && (index + 1)%7 != 0){
                        isfullChoice = false;
                        break;
                      }
                    }
                  }
                }else {
                  final int index = list[i].day + firstDayIsWeekInMonth;
                  returnList.remove(dateTime);
                  if(index%7 != 0 && (index + 1)%7 != 0){
                    isfullChoice = false;
                  }
                }
              }

次要的判断高度

double getBottomSheetHeight(DateTime date) {
    //当月的总天数
    final int currentMonthTotalDays = CommonUtils.getMonthDay(date);
    //每月的一号对应的周几(星期一在第二天)若星期一第一天就-1
    final int firstDayIsWeekInMonth = CommonUtils.computeFirstDay(date, MaterialLocalizations.of(context));
    final int line = ((currentMonthTotalDays + firstDayIsWeekInMonth)%7).toInt() == 0 ? 0 : 1;
    final lines = ((currentMonthTotalDays + firstDayIsWeekInMonth)/7).toInt();
    int column = lines + line ;
    final itemHeight = MediaQuery.of(context).size.width/7 ;
    return column * itemHeight + 15;
  }
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:30:55  更:2021-11-10 12:31:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:08:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码