You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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;
  },
)

代码说明

  1. holidayPredicate:负责判断当前日期是否属于节假日,通过把日期格式化为和数据源一致的字符串,比对是否存在于fetchMonthAttendance列表中。
  2. holidayBuilder:专门针对被标记为节假日的日期渲染自定义样式,这里设置了浅绿色背景和白色文字,你可以根据需求调整颜色、圆角等属性。
  3. 去掉了原代码中defaultBuilder里的遍历判断逻辑,避免了对普通日期渲染的干扰,同时提升了性能(不用每次渲染都遍历整个日期列表)。

内容的提问来源于stack exchange,提问作者Rajan Dhiman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:58:18