如何在TableCalendar组件中高亮显示节假日日期?
在Flutter TableCalendar中实现节假日日期高亮
要给TableCalendar里的节假日日期添加高亮效果,你可以通过组件自带的holidayPredicate和calendarBuilders.holidayBuilder配合实现,比你当前用defaultBuilder的方式更精准高效,还能避免样式冲突。以下是优化后的实现方案:
核心优化点
- 用
holidayPredicate明确标记节假日日期,让TableCalendar识别哪些是节假日 - 用
holidayBuilder专门自定义节假日的显示样式,不干扰普通日期、选中日期的原有样式
修改后的完整代码
TableCalendar( calendarFormat: CalendarFormat.month, daysOfWeekHeight: 20, daysOfWeekStyle: DaysOfWeekStyle( weekdayStyle: TextStyle().copyWith( color: Colors.black, fontWeight: FontWeight.w500, fontSize: 14.0, ), decoration: BoxDecoration( color: lightColor, borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ), ), ), headerStyle: HeaderStyle( decoration: BoxDecoration(), titleCentered: true, formatButtonVisible: false, leftChevronIcon: Icon( Icons.keyboard_arrow_left, color: buttoncolor, ), rightChevronIcon: Icon( Icons.keyboard_arrow_right, color: buttoncolor, ), titleTextStyle: TextStyle( fontSize: 18, fontWeight: FontWeight.w600, )), calendarStyle: CalendarStyle( markerSize: 40, outsideDaysVisible: false, todayTextStyle: TextStyle(color: Colors.black), todayDecoration: BoxDecoration( color: AppColor.transparent, shape: BoxShape.circle), selectedDecoration: BoxDecoration( color: AppColor.orange, border: Border.all( color: AppColor.orange, width: 1, strokeAlign: BorderSide.strokeAlignOutside, ), shape: BoxShape.circle, ), ), rowHeight: 35, firstDay: DateTime.now().subtract(Duration(days: 60)), lastDay: DateTime.now(), focusedDay: _currentDate, onDaySelected: (selectedDay, focusedDay) { if (!isSameDay(_selectedDate, selectedDay)) { setState(() { _selectedDate = selectedDay; _currentDate = focusedDay; controller.seeAttendance( context: context, selectedDate: _selectedDate); }); } }, // 标记节假日的判断逻辑 holidayPredicate: (day) { String formattedDay = "${day.year}-${day.month.toString().padLeft(2, '0')}-${day.day.toString().padLeft(2, '0')}"; return controller.fetchMonthAttendance.contains(formattedDay); }, calendarBuilders: CalendarBuilders( // 自定义节假日的显示样式 holidayBuilder: (context, day, focusedDay) { return Container( decoration: const BoxDecoration( color: Colors.lightGreen, borderRadius: BorderRadius.all( Radius.circular(8.0), ), ), child: Center( child: Text( '${day.day}', style: const TextStyle(color: Colors.white), ), ), ); }, ), selectedDayPredicate: (day) { return isSameDay(_selectedDate, day); }, onFormatChanged: (format) { if (_calendarFormat != format) { setState(() { _calendarFormat = format; }); } }, onPageChanged: (focusedDay) { _currentDate = focusedDay; }, )
代码说明
- holidayPredicate:负责判断当前日期是否属于节假日,通过把日期格式化为和数据源一致的字符串,比对是否存在于
fetchMonthAttendance列表中。 - holidayBuilder:专门针对被标记为节假日的日期渲染自定义样式,这里设置了浅绿色背景和白色文字,你可以根据需求调整颜色、圆角等属性。
- 去掉了原代码中
defaultBuilder里的遍历判断逻辑,避免了对普通日期渲染的干扰,同时提升了性能(不用每次渲染都遍历整个日期列表)。
内容的提问来源于stack exchange,提问作者Rajan Dhiman
相关产品推荐
相关产品推荐

