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

如何将Flutter table_calendar改为类似谷歌日历的预约直显样式?

实现TableCalendar类似谷歌日历的事件展示样式

要实现把预约内容直接显示在日期下方的效果,你需要自定义TableCalendar的日期单元格,核心是用calendarBuilders参数替换默认的标记点渲染逻辑,下面是具体步骤和代码示例:


1. 定义事件数据结构

先创建一个简单的Event类,用来存储预约的标题和颜色:

class Event {
  final String title;
  final Color color;

  const Event(this.title, {this.color = Colors.blue});
}

在页面的State中准备测试用的事件数据(实际项目中可以从接口或本地存储获取):

final Map<DateTime, List<Event>> _events = {
  DateTime.now(): [
    const Event('上午部门会议'),
    const Event('下午团建', color: Colors.green),
  ],
  DateTime.now().add(const Duration(days: 1)): [
    const Event('客户拜访', color: Colors.orange),
  ],
};

2. 配置TableCalendar的自定义构建器

在TableCalendar组件中,通过calendarBuilders自定义日期单元格的渲染逻辑,同时调整单元格高度给事件留出显示空间:

TableCalendar(
  firstDay: DateTime.utc(2020, 1, 1),
  lastDay: DateTime.utc(2030, 12, 31),
  focusedDay: DateTime.now(),
  events: _events,
  // 调整单元格高度,适配事件显示
  calendarStyle: const CalendarStyle(
    cellHeight: 80,
  ),
  calendarBuilders: CalendarBuilders(
    // 自定义默认日期单元格
    defaultBuilder: (context, date, events) => _buildDateCell(date, events),
    // 自定义选中日期的单元格样式
    selectedBuilder: (context, date, events) => Container(
      decoration: BoxDecoration(
        color: Colors.blueAccent,
        borderRadius: BorderRadius.circular(8),
      ),
      child: _buildDateCell(date, events, isSelected: true),
    ),
    // 自定义今日单元格样式
    todayBuilder: (context, date, events) => Container(
      decoration: BoxDecoration(
        color: Colors.blue.withOpacity(0.2),
        borderRadius: BorderRadius.circular(8),
      ),
      child: _buildDateCell(date, events),
    ),
  ),
)

3. 编写日期单元格的构建方法

实现_buildDateCell方法,把日期数字和事件列表组合成一个完整的单元格:

Widget _buildDateCell(DateTime date, List<Event> events, {bool isSelected = false}) {
  final textColor = isSelected ? Colors.white : Colors.black;
  return Padding(
    padding: const EdgeInsets.all(4.0),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // 显示日期数字
        Center(
          child: Text(
            '${date.day}',
            style: TextStyle(color: textColor, fontWeight: FontWeight.w500),
          ),
        ),
        const SizedBox(height: 2),
        // 显示事件列表
        Expanded(
          child: ListView.builder(
            physics: const NeverScrollableScrollPhysics(), // 禁止单元格内滚动
            itemCount: events.length,
            itemBuilder: (context, index) {
              final event = events[index];
              return Container(
                margin: const EdgeInsets.symmetric(vertical: 1, horizontal: 2),
                padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1),
                decoration: BoxDecoration(
                  color: event.color.withOpacity(0.8),
                  borderRadius: BorderRadius.circular(4),
                ),
                child: Text(
                  event.title,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 10,
                  ),
                  overflow: TextOverflow.ellipsis, // 超出文本省略
                ),
              );
            },
          ),
        ),
      ],
    ),
  );
}

额外调整建议

  • 可以根据需求修改cellHeight、事件条目的字体大小、颜色、圆角等参数,匹配谷歌日历的视觉风格
  • 如果事件数量过多,可限制显示的事件条数,或者开启单元格内滚动(去掉NeverScrollableScrollPhysics)
  • 记得在文件顶部导入table_calendar包:import 'package:table_calendar/table_calendar.dart';

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 12:35:19