Flutter仿钉钉考勤日历的示例代码

这篇文章主要介绍了Flutter仿钉钉考勤日历的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

本文主要介绍了Flutter仿钉钉考勤日历的示例代码,分享给大家,具体如下:

效果

原型

开发

1. 使用

 // 考勤日历 DatePickerDialog( initialDate: DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2030), onDateChanged: onDateChanged, // 0:无状态,1:正常考勤  2:异常考情,迟到,早退, // 若不满一个月,日历会自动用0补满一个月 checking: [ 0, 0, 1, 2, ], ), 

DatePickerDialog是在存在与Flutter的material包中,Flutter自带的日历是以dialog形式存在的,本文将dialog改成StatefulWidget直接在页面中,将多余东西去掉,直接在material/calendar_date_picker.dart中_DayPicker上进行修改。

2. 修改日历中日期样式:

 Widget dayWidget = Container( margin: EdgeInsets.all(4.0), decoration: decoration, alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(localizations.formatDecimal(day), style: TextStyle( fontSize: 14.0, color: dayColor, fontWeight: FontWeight.bold)), Visibility( visible: checking[day - 1] == 1 || checking[day - 1] == 2, child: Container( height: 6.0, width: 6.0, decoration: BoxDecoration( shape: BoxShape.circle, color: isSelectedDay ? Colors.white : (checking[day - 1] == 1 ?  Color(0xFF1376EE): Color(0xFFFF8A21)), ), ), ), ], ), ); 

Visibility原来没有,是修改加上去的,主要是显示当天打卡状态,若打卡正常则在日期显示下方显示蓝色小点,若有异常则显示橙色的点,若没有状态就不显示,checking则是使用DatePickerDialog传入的,由于日历从1开始,数组是从索引0开始的,所以使用checking[day - 1]才能准确获取某一日的打卡状态,day 则是日历中某一月中所有日期。

3.设置星期标题

修改后:

 List _dayHeaders() { final List result = []; final List weekdays = ["日", "一", "二", "三", "四", "五", "六"]; for (int i = 1; true; i = (i + 1) % 7) { final String weekday = weekdays[i]; result.add(ExcludeSemantics( child: Center( child: Text(weekday, style: TextStyle(fontSize: 14.0, color: Color(0xFF999999)))), )); if (i == (1 - 1) % 7) break; } return result; } 

原文:

 List _dayHeaders(TextStyle? headerStyle, MaterialLocalizations localizations) { final List result = []; for (int i = localizations.firstDayOfWeekIndex; true; i = (i + 1) % 7) { final String weekday = localizations.narrowWeekdays[i]; result.add(ExcludeSemantics( child: Center(child: Text(weekday, style: headerStyle)), )); if (i == (localizations.firstDayOfWeekIndex - 1) % 7) break; } return result; } 

localizations.firstDayOfWeekIndex返回值为0或者1,若返回0,则星期日为每周的第一天;若返回1,则星期一为每周的第一天。本文中没有从localizations.firstDayOfWeekIndex获取,直接赋值为1,则每周从星期一开始。

4.补全每个月空白日期:

获取指定月份有多少天

 static int getDaysInMonth(int year, int month) { if(month <1){ year = year - 1; month = month + 12; } if(month > 12){ year = year + 1; month = month - 12; } if (month == DateTime.february) { final bool isLeapYear = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0); return isLeapYear ? 29 : 28; } const List daysInMonth = [31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; return daysInMonth[month - 1]; } 

获取指定月份1日的偏移量,即每个月第一天是星期几,若1号是星期3,因为日历每周是从第一天开始的,所以第一周的星期的星期一,星期二为空白,需要补全上个月的倒数后两天,所以还需要获取上个月的最后两天是哪两天。

 // 获取日期偏移 static int firstDayOffsets(int year, int month) { final int weekdayFromMonday = DateTime(year, month).weekday - 1; int firstDayOfWeekIndex = 1; firstDayOfWeekIndex = (firstDayOfWeekIndex - 1) % 7; return (weekdayFromMonday - firstDayOfWeekIndex) % 7; } ... // 补全开始日期 int day = -dayOffset; while (day 

补全日历结束日期,每个月最后一天若为星期日,则无需补全,若为星期五则把下个月的前两天补在本月的星期六和星期日:

 if ((daysInMonth + dayOffset) % 7 > 0) { // 计算需要补多少天,直接从1开始就好 int addNum = 7 - ((daysInMonth + dayOffset) % 7); for (int i = 1; i <= addNum; i++) { dayItems.add(Container( margin: EdgeInsets.all(4.0), alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text(localizations.formatDecimal(i), style: TextStyle( fontSize: 14.0, color: Color(0xFF888888), fontWeight: FontWeight.bold)), Visibility( visible: false, child: Container( height: 6.0, width: 6.0, decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFFFF8A21), ), ), ), ], ), )); } }

计算每个月从星期一开始展示可以展示几行,即计算日历高度,月份不同,高度不同,最少4行,最多6行,根据内容动态显示不至于留大量空白

 // 计算一个月有多少天 int daysInMonth = ChinaDateUtils.getDaysInMonth( widget.initialDate.year, widget.initialDate.month); // 计算每个月第一天的星期 int dayOffset = ChinaDateUtils.firstDayOffsets( widget.initialDate.year, widget.initialDate.month); // 计算用多少行展示所有日期 int row = ((daysInMonth + dayOffset) / 7).ceil(); 

修改这些内容大概可以实现上述效果。

Demo地址:https://gitee.com/masshub/sign_in

以上就是Flutter仿钉钉考勤日历的示例代码的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 移动