Flutter日历展示插件table_calendar的使用
Flutter日历展示插件table_calendar的使用
TableCalendar
TableCalendar是一个高度可定制、功能丰富的Flutter日历组件。
特性 | 描述 |
---|---|
![]() |
TableCalendar with custom styles |
![]() |
TableCalendar with custom builders |
Features
- 简单易用的API
- 可自定义样式的预配置UI
- 支持自定义构建器以实现无限UI设计
- 支持多语言
- 支持范围选择和多选
- 动态事件和节日
- 垂直自动调整大小,适应内容或填充视口
- 多种日历格式(月、两周、周)
- 水平滑动边界(第一天、最后一天)
Usage
Installation
在pubspec.yaml
中添加以下依赖:
dependencies:
table_calendar: ^3.2.0
Basic Setup
完整的示例代码可以在这里找到。
初始化TableCalendar
TableCalendar(
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
);
firstDay
:日历最早可访问的日期。lastDay
:日历最晚可访问的日期。focusedDay
:当前聚焦的日期。
添加交互性
为了让日历响应用户的点击操作,并标记选中的日期,可以添加以下回调函数:
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay; // 更新 `_focusedDay`
});
},
为了动态更新可见的日历格式,可以添加以下代码:
calendarFormat: _calendarFormat,
onFormatChanged: (format) {
setState(() {
_calendarFormat = format;
});
},
更新focusedDay
为了避免每次热重载时日历回到初始状态,需要更新focusedDay
:
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
Events
完整的事件示例代码可以在这里找到。
可以通过eventLoader
属性为TableCalendar提供自定义事件:
eventLoader: (day) {
return _getEventsForDay(day);
},
例如,使用LinkedHashMap
来存储事件:
final events = LinkedHashMap(
equals: isSameDay,
hashCode: getHashCode,
)..addAll(eventSource);
List<Event> _getEventsForDay(DateTime day) {
return events[day] ?? [];
}
循环事件
通过eventLoader
可以轻松添加循环事件。例如,每周一添加一个事件:
eventLoader: (day) {
if (day.weekday == DateTime.monday) {
return [Event('Cyclic event')];
}
return [];
},
选中事件
当用户点击某天时,获取该天的事件列表:
void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
if (!isSameDay(_selectedDay, selectedDay)) {
setState(() {
_focusedDay = focusedDay;
_selectedDay = selectedDay;
_selectedEvents = _getEventsForDay(selectedDay);
});
}
}
Custom UI with CalendarBuilders
通过CalendarBuilders
可以自定义UI。例如,只覆盖周日的标签:
calendarBuilders: CalendarBuilders(
dowBuilder: (context, day) {
if (day.weekday == DateTime.sunday) {
final text = DateFormat.E().format(day);
return Center(
child: Text(
text,
style: TextStyle(color: Colors.red),
),
);
}
},
),
Locale
通过locale
属性设置日历的语言。例如,设置为波兰语:
TableCalendar(
locale: 'pl_PL',
),
初始化
如果需要使用其他语言,首先需要初始化日期格式化:
import 'package:intl/date_symbol_data_local.dart';
void main() {
initializeDateFormatting().then((_) => runApp(MyApp()));
}
示例代码
以下是main.dart
的完整示例代码:
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:table_calendar_example/pages/basics_example.dart';
import 'package:table_calendar_example/pages/complex_example.dart';
import 'package:table_calendar_example/pages/events_example.dart';
import 'package:table_calendar_example/pages/multi_example.dart';
import 'package:table_calendar_example/pages/range_example.dart';
void main() {
initializeDateFormatting().then((_) => runApp(const MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TableCalendar Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const StartPage(),
);
}
}
class StartPage extends StatefulWidget {
const StartPage({super.key});
@override
State<StartPage> createState() => _StartPageState();
}
class _StartPageState extends State<StartPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('TableCalendar Example'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 20.0),
ElevatedButton(
child: const Text('Basics'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TableBasicsExample()),
),
),
const SizedBox(height: 12.0),
ElevatedButton(
child: const Text('Range Selection'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TableRangeExample()),
),
),
const SizedBox(height: 12.0),
ElevatedButton(
child: const Text('Events'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TableEventsExample()),
),
),
const SizedBox(height: 12.0),
ElevatedButton(
child: const Text('Multiple Selection'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TableMultiExample()),
),
),
const SizedBox(height: 12.0),
ElevatedButton(
child: const Text('Complex'),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const TableComplexExample()),
),
),
const SizedBox(height: 20.0),
],
),
),
);
}
}
希望这些信息能帮助你更好地理解和使用table_calendar
插件!如果有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter日历展示插件table_calendar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter项目中使用table_calendar
插件来展示日历的示例代码。这个示例将展示如何集成table_calendar
插件,并处理日历的选择事件。
首先,你需要在pubspec.yaml
文件中添加table_calendar
依赖:
dependencies:
flutter:
sdk: flutter
table_calendar: ^3.0.5 # 请检查最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Flutter项目中创建一个展示日历的页面。以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Calendar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CalendarPage(),
);
}
}
class CalendarPage extends StatefulWidget {
@override
_CalendarPageState createState() => _CalendarPageState();
}
class _CalendarPageState extends State<CalendarPage> with SingleTickerProviderStateMixin {
CalendarController _controller;
Map<DateTime, List<dynamic>> _events;
@override
void initState() {
super.initState();
_controller = CalendarController();
// 初始化一些示例事件
_events = {};
// 添加一些示例事件到特定日期
_addEvent(DateTime date, String title) {
if (!_events.containsKey(date)) {
_events[date] = [];
}
_events[date]!.add(title);
}
// 添加一些示例数据
_addEvent(DateTime(2023, 10, 5), 'Event 1');
_addEvent(DateTime(2023, 10, 15), 'Event 2');
_addEvent(DateTime(2023, 10, 25), 'Event 3');
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter Calendar Demo'),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TableCalendar(
_controller,
events: _events,
initialCalendarFormat: CalendarFormat.month,
startingDayOfWeek: StartingDayOfWeek.monday,
calendarStyle: CalendarStyle(
todayColor: Colors.blue,
selectedColor: Colors.deepOrange.withOpacity(0.3),
todayStyle: TextStyle(fontWeight: FontWeight.bold),
selectedTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
daysOfWeekStyle: TextStyle(color: Colors.grey[800]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
decoration: BoxDecoration(
color: Colors.blue,
),
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, events) => Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.deepOrange,
shape: BoxShape.circle,
),
child: Text(
date.day.toString(),
style: TextStyle(color: Colors.white),
),
),
todayDayBuilder: (context, date, events) => Container(
margin: const EdgeInsets.all(4.0),
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
shape: BoxShape.circle,
),
child: Text(
date.day.toString(),
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
),
),
markerBuilder: (context, date, events) => Badge(
badgeContent: Text(events.length.toString()),
),
),
onDaySelected: (date, events) {
setState(() {});
},
onVisibleDaysChanged: (days, month) {
setState(() {});
},
onCalendarCreated: (CalendarController controller) {
setState(() {});
},
),
// 显示选定日期的事件
SizedBox(height: 10.0),
Expanded(
child: _buildEventList(),
),
],
),
),
);
}
Widget _buildEventList() {
return ListView.builder(
shrinkWrap: true,
itemCount: _controller.selectedEvents.length,
itemBuilder: (context, index) {
final event = _controller.selectedEvents[index];
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10),
),
margin: EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
child: ListTile(
leading: Icon(Icons.event),
title: Text(event.toString()),
),
);
},
);
}
}
class Badge extends StatelessWidget {
final Widget badgeContent;
const Badge({Key? key, required this.badgeContent}) : super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.topRight,
children: <Widget>[
Positioned(
right: -4,
top: -4,
child: Container(
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.redAccent,
borderRadius: BorderRadius.circular(6),
),
constraints: BoxConstraints(minWidth: 18, minHeight: 18),
child: badgeContent,
),
),
],
);
}
}
在这个示例中,我们做了以下几件事:
- 初始化
CalendarController
:用于控制日历的显示和行为。 - 初始化事件数据:
_events
是一个映射,将日期映射到事件列表。 - 构建日历:使用
TableCalendar
小部件,并配置样式和事件构建器。 - 处理选择事件:通过
onDaySelected
回调处理日期选择事件。 - 显示选定日期的事件:在日历下方显示选定日期的事件列表。
这个示例代码提供了一个基础的日历展示和处理事件的框架,你可以根据需要进一步自定义和扩展。