如何将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
相关产品推荐
相关产品推荐

