当前位置: 首页 > wzjs >正文

长春网站建设找新生科技沈阳德泰诺网站建设公司 概况

长春网站建设找新生科技,沈阳德泰诺网站建设公司 概况,众筹网站制作,不得不知道网站pub dev:table_calendar 3.2.0 我来详细解释 TableCalendar 是如何根据不同的 CalendarFormat 来显示界面的。主要逻辑在 CalendarCore 中实现。 核心逻辑分为以下几个部分: 页面数量计算 - _getPageCount 方法根据不同格式计算总页数: in…

pub dev:table_calendar 3.2.0
我来详细解释 TableCalendar 是如何根据不同的 CalendarFormat 来显示界面的。主要逻辑在 CalendarCore 中实现。
核心逻辑分为以下几个部分:

  1. 页面数量计算 - _getPageCount 方法根据不同格式计算总页数:
int _getPageCount(CalendarFormat format, DateTime first, DateTime last) {switch (format) {case CalendarFormat.month:return _getMonthCount(first, last) + 1;case CalendarFormat.twoWeeks:return _getTwoWeekCount(first, last) + 1;case CalendarFormat.week:return _getWeekCount(first, last) + 1;}
}
  1. 可见日期范围计算 - _getVisibleRange 方法决定每种格式显示多少天:
DateTimeRange _getVisibleRange(CalendarFormat format, DateTime focusedDay) {switch (format) {case CalendarFormat.month:return _daysInMonth(focusedDay);  // 显示整月case CalendarFormat.twoWeeks:return _daysInTwoWeeks(focusedDay);  // 显示两周case CalendarFormat.week:return _daysInWeek(focusedDay);  // 显示一周}
}
  1. 行数计算 - _getRowCount 方法决定显示多少行:
int _getRowCount(CalendarFormat format, DateTime focusedDay) {if (format == CalendarFormat.twoWeeks) {return 2;  // 两周显示2行} else if (format == CalendarFormat.week) {return 1;  // 一周显示1行} else if (sixWeekMonthsEnforced) {return 6;  // 月视图强制6行}// 月视图动态计算行数final first = _firstDayOfMonth(focusedDay);final daysBefore = _getDaysBefore(first);final firstToDisplay = first.subtract(Duration(days: daysBefore));final last = _lastDayOfMonth(focusedDay);final daysAfter = _getDaysAfter(last);final lastToDisplay = last.add(Duration(days: daysAfter));return (lastToDisplay.difference(firstToDisplay).inDays + 1) ~/ 7;
}
  1. 日期生成 - 根据不同格式生成要显示的日期:
// 生成一周的日期
DateTimeRange _daysInWeek(DateTime focusedDay) {final daysBefore = _getDaysBefore(focusedDay);final firstToDisplay = focusedDay.subtract(Duration(days: daysBefore));final lastToDisplay = firstToDisplay.add(const Duration(days: 7));return DateTimeRange(start: firstToDisplay, end: lastToDisplay);
}// 生成两周的日期
DateTimeRange _daysInTwoWeeks(DateTime focusedDay) {final daysBefore = _getDaysBefore(focusedDay);final firstToDisplay = focusedDay.subtract(Duration(days: daysBefore));final lastToDisplay = firstToDisplay.add(const Duration(days: 14));return DateTimeRange(start: firstToDisplay, end: lastToDisplay);
}// 生成一个月的日期
DateTimeRange _daysInMonth(DateTime focusedDay) {final first = _firstDayOfMonth(focusedDay);final daysBefore = _getDaysBefore(first);final firstToDisplay = first.subtract(Duration(days: daysBefore));if (sixWeekMonthsEnforced) {// 强制显示6周final end = firstToDisplay.add(const Duration(days: 42));return DateTimeRange(start: firstToDisplay, end: end);}// 根据实际天数显示final last = _lastDayOfMonth(focusedDay);final daysAfter = _getDaysAfter(last);final lastToDisplay = last.add(Duration(days: daysAfter));return DateTimeRange(start: firstToDisplay, end: lastToDisplay);
}
  1. 页面切换逻辑 - _getFocusedDay 方法处理不同格式下的页面切换:
DateTime _getFocusedDay(CalendarFormat format,DateTime prevFocusedDay,int pageIndex,
) {if (pageIndex == previousIndex) {return prevFocusedDay;}final pageDif = pageIndex - previousIndex!;DateTime day;switch (format) {case CalendarFormat.month:// 月视图按月切换day = DateTime.utc(prevFocusedDay.year, prevFocusedDay.month + pageDif);case CalendarFormat.twoWeeks:// 两周视图每次移动14天day = DateTime.utc(prevFocusedDay.year,prevFocusedDay.month,prevFocusedDay.day + pageDif * 14,);case CalendarFormat.week:// 周视图每次移动7天day = DateTime.utc(prevFocusedDay.year,prevFocusedDay.month,prevFocusedDay.day + pageDif * 7,);}// 确保不超出范围if (day.isBefore(firstDay)) {day = firstDay;} else if (day.isAfter(lastDay)) {day = lastDay;}return day;
}

如果你想添加新的 CalendarFormat(比如 threeWeeks),需要:

  • 在 utils.dart 中的 CalendarFormat 枚举中添加新格式
  • 在上述所有 switch 语句中添加新的 case 处理
  • 实现对应的日期范围计算方法
  • 添加行数计算逻辑

例如添加 threeWeeks 格式

// 1. 在 CalendarFormat 中添加
enum CalendarFormat { month, twoWeeks, week, threeWeeks }// 2. 在 switch 语句中添加处理
case CalendarFormat.threeWeeks:return _daysInThreeWeeks(focusedDay);// 3. 实现日期范围计算
DateTimeRange _daysInThreeWeeks(DateTime focusedDay) {final daysBefore = _getDaysBefore(focusedDay);final firstToDisplay = focusedDay.subtract(Duration(days: daysBefore));final lastToDisplay = firstToDisplay.add(const Duration(days: 21));return DateTimeRange(start: firstToDisplay, end: lastToDisplay);
}// 4. 添加行数计算
if (format == CalendarFormat.threeWeeks) {return 3;  // 三周显示3行
}

TableCalendar 的界面绘制流程

让我详细解释 TableCalendar 的界面绘制流程。整个日历界面的绘制主要涉及以下组件的配合:
TableCalendar (主组件) -> CalendarCore (核心布局) -> CalendarPage (单页渲染)
让我们从最内层的 CalendarPage 开始解释:

  1. CalendarPage - 单个日历页面的渲染
class CalendarPage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Row(children: [// 1. 可选的周数显示列if (weekNumberVisible) _buildWeekNumbers(context),// 2. 主日历表格Expanded(child: Table(border: tableBorder,children: [// 2.1 星期头部行 (Mon, Tue, Wed...)if (dowVisible) _buildDaysOfWeek(context),// 2.2 日期行..._buildCalendarDays(context),],),),],);}
}

日历页面使用 Table widget 来布局,包含:
可选的周数列
星期头部行
日期网格
2. CalendarCore - 页面管理与切换

class CalendarCore extends StatelessWidget {@overrideWidget build(BuildContext context) {return PageView.builder(controller: pageController,itemCount: _getPageCount(calendarFormat, firstDay, lastDay),itemBuilder: (context, index) {// 1. 计算这一页要显示的基准日期final baseDay = _getBaseDay(calendarFormat, index);// 2. 计算这一页要显示的日期范围final visibleRange = _getVisibleRange(calendarFormat, baseDay);// 3. 生成要显示的所有日期final visibleDays = _daysInRange(visibleRange.start, visibleRange.end);// 4. 计算行高final actualDowHeight = dowVisible ? dowHeight! : 0.0;final constrainedRowHeight = constraints.hasBoundedHeight? (constraints.maxHeight - actualDowHeight) / _getRowCount(calendarFormat, baseDay): null;// 5. 渲染日历页面return CalendarPage(visibleDays: visibleDays,// ... 其他配置);},);}
}
  1. 实际的渲染过程
    以月视图为例,完整的渲染流程:
// 1. 确定要显示的日期范围
DateTimeRange _daysInMonth(DateTime focusedDay) {// 获取月份第一天final first = _firstDayOfMonth(focusedDay);  // 例如:2024-03-01// 计算需要显示的上月剩余天数final daysBefore = _getDaysBefore(first);    // 如果3月1日是周五,需要显示前4天// 计算本月第一个显示的日期final firstToDisplay = first.subtract(Duration(days: daysBefore));  // 2024-02-26if (sixWeekMonthsEnforced) {// 强制显示6周final end = firstToDisplay.add(const Duration(days: 42));  // 显示42天return DateTimeRange(start: firstToDisplay, end: end);}// 获取月份最后一天final last = _lastDayOfMonth(focusedDay);    // 2024-03-31// 计算需要显示的下月天数final daysAfter = _getDaysAfter(last);       // 补充到完整的周// 计算最后一个显示的日期final lastToDisplay = last.add(Duration(days: daysAfter));  // 2024-04-06return DateTimeRange(start: firstToDisplay, end: lastToDisplay);
}// 2. 生成所有要显示的日期
List<DateTime> _daysInRange(DateTime first, DateTime last) {final dayCount = last.difference(first).inDays + 1;return List.generate(dayCount,(index) => DateTime.utc(first.year, first.month, first.day + index),);
}// 3. 渲染表格
List<TableRow> _buildCalendarDays(BuildContext context) {final rowAmount = visibleDays.length ~/ 7;  // 计算行数return List.generate(rowAmount,(row) => TableRow(decoration: rowDecoration,children: List.generate(7,(column) => dayBuilder(context, visibleDays[row * 7 + column]),),),);
}

视觉效果示意:

     March 2024
Mo Tu We Th Fr Sa Su
26 27 28 29  1  2  3  <- 上月日期4  5  6  7  8  9 10  <- 本月第一周
11 12 13 14 15 16 17  <- 本月第二周
18 19 20 21 22 23 24  <- 本月第三周
25 26 27 28 29 30 31  <- 本月第四周1  2  3  4  5  6  7  <- 下月日期

不同的 CalendarFormat 只是改变了显示的行数:

  • CalendarFormat.month: 显示整月(4-6行)
  • CalendarFormat.twoWeeks: 显示2行
  • CalendarFormat.week: 显示1行
    每个日期单元格的具体样式由 dayBuilder 控制,可以通过 CalendarBuilders 和 CalendarStyle 来自定义外观。
    这就是整个 TableCalendar 的界面渲染流程。它通过 PageView 实现翻页,通过 Table 实现网格布局,通过精确的日期计算确保日历的正确显示

其中函数_buildCalendarDays的解释如下:
让我们一步步解析:

  1. 函数声明:
    • List 表示返回一个 TableRow 类型的列表
      List.generate(count, (index) => value)
      下划线 _ 开头表示这是一个私有方法
      BuildContext context 是 Flutter 中用于构建 Widget 的上下文参数
  2. 行数计算:
   final rowAmount = visibleDays.length ~/ 7;
- ~/ 是整数除法运算符
比如如果 visibleDays.length 是 35,那么 rowAmount 就是 5
  1. List.generate: List.generate(count, (index) => value)
    这是 Dart 的列表生成方法
    count 指定要生成多少个元素
    (index) => value 是一个函数,用于生成每个元素
  2. TableRow:
    • Flutter 中表格的一行
      decoration 用于设置行的样式(比如背景色)
      children 包含这一行的所有单元格
  3. 嵌套的 List.generate:
    • 生成每行的 7 个单元格
      index * 7 + id 计算当前单元格对应的日期索引
      dayBuilder 用于构建每个日期的显示内容

举个例子,如果你要显示一个月的日历:
假设有 35 天要显示(5 周)
rowAmount 将是 5(35/7)
外层 List.generate 会生成 5 行
每行内部的 List.generate 会生成 7 个单元格
最终生成一个 5×7 的表格
这就像在创建一个 Excel 表格:
每个单元格的具体显示内容由 dayBuilder 决定,这就是为什么它是一个可自定义的函数。

生成视图的流程

  1. 初始化阶段:
// 在测试代码中初始化 TableCalendarBase
TableCalendarBase(dayBuilder: (context, day, focusedDay) {return Text('${day.day}',key: dateToKey(day),);},// ... 其他参数
)
  1. CalendarCore 中的包装:
// CalendarCore 给每个日期添加固定高度的容器
dayBuilder: (context, day) {// ... 计算 baseDay ...return SizedBox(height: constrainedRowHeight ?? rowHeight,child: dayBuilder(context, day, baseDay),  // 调用原始的 dayBuilder);
}
  1. CalendarPage 中的布局:
// CalendarPage 将日期排列成表格
List<TableRow> _buildCalendarDays(BuildContext context) {return List.generate(rowAmount,  // 行数(index) => TableRow(children: List.generate(7,  // 每行7列(id) => dayBuilder(context, visibleDays[index * 7 + id]),  // 调用包装后的 dayBuilder),),);
}

所以完整流程是:
用户提供基础的日期显示方式(Text组件)
CalendarCore 添加大小控制(SizedBox)
CalendarPage 将所有日期组织成表格形式(Table和TableRow)
最终形成一个完整的日历视图
这就像搭积木:
Text(显示日期)
→ SizedBox(控制大小)
→ TableRow(排成一行)
→ Table(组成表格)
→ 完整日历


文章转载自:

http://Um4jNAmT.thpns.cn
http://CpT0Xfg6.thpns.cn
http://RNjXU5JE.thpns.cn
http://h72Tt9fy.thpns.cn
http://nAVBcS4H.thpns.cn
http://jmHWOHuR.thpns.cn
http://6Z8SxfGP.thpns.cn
http://UigM0nLg.thpns.cn
http://8DeQ4VIE.thpns.cn
http://mFA1fCET.thpns.cn
http://ETg7k1R9.thpns.cn
http://wqF5iz75.thpns.cn
http://nyZAsSDv.thpns.cn
http://RA7eTS5O.thpns.cn
http://jjVgSLSd.thpns.cn
http://MgKTaYyV.thpns.cn
http://VYewucNF.thpns.cn
http://AFMSoWmK.thpns.cn
http://YLL8axIu.thpns.cn
http://TNHObnS9.thpns.cn
http://T1k8M2AM.thpns.cn
http://yHySC5hv.thpns.cn
http://fCmoPNSb.thpns.cn
http://pG6rPQgY.thpns.cn
http://gvEsC8pl.thpns.cn
http://6EbqbN8O.thpns.cn
http://fte2ngEq.thpns.cn
http://q3ElbtGT.thpns.cn
http://lxl3DQha.thpns.cn
http://dhuOMK0v.thpns.cn
http://www.dtcms.com/wzjs/750790.html

相关文章:

  • 网站一定要备案外贸建站应该怎么做
  • 小型教育网站建设问题存在的广州企业网站开发
  • 怎么做 在线电影网站企业网站模板psd
  • 网站设计工程师是it行业吗新安网站开发
  • 西安做兼职网站惠州网站设计培训
  • rails 网站开发wordpress编辑文章手机版
  • 攀枝花网站怎么做seo做网站厂家
  • 岳阳网站建设网站360做的网站首页
  • 湖北省住房和城乡建设部网站用照片做视频的网站
  • 手机网站制作费用网站建设登录注册怎么做
  • 用ps做网站页面的大小建设网站有哪些好处和坏处
  • seo网站分析工具成都旅游住哪里
  • 建设茶网站目的个人求职网站如何做
  • 一般找素材都是做哪几个网站呢可以做水果的团购网站
  • 网站建设力度不够论文做家居建材出口网站有哪些
  • 企业官方网站建设费用先备案域名还是先做网站
  • 做百度竞价对网站有无要求徐州东站
  • 最早做网站的那批人网站源码 带数据
  • 上海网站建设网asp网站制作设计教程
  • 网站推广方案编写网站优化推广的方法
  • 门户网站建设方案模板长沙本地推广平台
  • 重庆网站平台如何推广.net网站开发免费教程
  • 云南省滇中引水工程建设管理局网站腾讯云网站建设教学视频
  • 经济研究院网站建设方案软件技术方案
  • 龙岗 网站建设专业网站设计工作室
  • 山东大学网站设计与建设网站开发到上线需要多久
  • 重庆放心seo整站优化微网站建设的三个步骤
  • 美食网站设计论文松江企业网站建设
  • 网站建设邀标书镇江网站设计多少钱
  • 做seo比较好的网站wordpress 两个主题