Flutter日历插件table_calendar_null_safe的使用
Flutter日历插件table_calendar_null_safe的使用
功能特性
- 广泛且易于使用的API
- 真正灵活的UI自定义构建器
- 完全的程序化控制通过
CalendarController
- 动态事件
- 节假日接口
- 语言本地化支持
- 垂直自动调整大小
- 美丽的动画
- 手势处理
- 多种日历格式
- 多种星期格式
- 指定可用日期范围
- 出色且可配置的UI
安装
在 pubspec.yaml
文件中添加依赖:
dependencies:
table_calendar_null_safe: ^2.0.0
然后在你的项目中导入它:
import 'package:table_calendar_null_safe/table_calendar.dart';
最后创建一个带有CalendarController
的TableCalendar
:
class _MyHomePageState extends State<MyHomePage> {
late CalendarController _calendarController;
[@override](/user/override)
void initState() {
super.initState();
_calendarController = CalendarController();
}
[@override](/user/override)
void dispose() {
_calendarController.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return TableCalendar(
calendarController: _calendarController,
);
}
}
语言本地化
Table Calendar
支持多种语言。要将日历显示为特定语言,请使用locale
属性。如果不指定,将使用默认语言。
TableCalendar(
calendarController: _calendarController,
locale: 'zh_CN', // 设置为中文
);
示例代码
以下是完整的示例代码,展示了如何使用table_calendar_null_safe
插件创建一个功能丰富的日历应用。
// Copyright (c) 2019 Aleksander Woźniak
// Licensed under Apache License v2.0
import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:table_calendar_null_safe/table_calendar_null_safe.dart';
// 示例节假日
final Map<DateTime, List> _holidays = {
DateTime(2020, 1, 1): ['新年'],
DateTime(2020, 1, 6): ['主显节'],
DateTime(2020, 2, 14): ['情人节'],
DateTime(2020, 4, 21): ['复活节星期天'],
DateTime(2020, 4, 22): ['复活节星期一'],
};
void main() {
initializeDateFormatting().then((_) => runApp(MyApp()));
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Table Calendar Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Table Calendar Demo'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, this.title}) : super(key: key);
final String? title;
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
Map<DateTime, List>? _events;
List? _selectedEvents;
late AnimationController _animationController;
late CalendarController _calendarController;
[@override](/user/override)
void initState() {
super.initState();
final _selectedDay = DateTime.now();
_events = {
_selectedDay.subtract(Duration(days: 30)): [
'活动A0',
'活动B0',
'活动C0'
],
_selectedDay.subtract(Duration(days: 27)): ['活动A1'],
_selectedDay.subtract(Duration(days: 20)): [
'活动A2',
'活动B2',
'活动C2',
'活动D2'
],
_selectedDay.subtract(Duration(days: 16)): ['活动A3', '活动B3'],
_selectedDay.subtract(Duration(days: 10)): [
'活动A4',
'活动B4',
'活动C4'
],
_selectedDay.subtract(Duration(days: 4)): [
'活动A5',
'活动B5',
'活动C5'
],
_selectedDay.subtract(Duration(days: 2)): ['活动A6', '活动B6'],
_selectedDay: ['活动A7', '活动B7', '活动C7', '活动D7'],
_selectedDay.add(Duration(days: 1)): [
'活动A8',
'活动B8',
'活动C8',
'活动D8'
],
_selectedDay.add(Duration(days: 3)):
Set.from(['活动A9', '活动A9', '活动B9']).toList(),
_selectedDay.add(Duration(days: 7)): [
'活动A10',
'活动B10',
'活动C10'
],
_selectedDay.add(Duration(days: 11)): ['活动A11', '活动B11'],
_selectedDay.add(Duration(days: 17)): [
'活动A12',
'活动B12',
'活动C12',
'活动D12'
],
_selectedDay.add(Duration(days: 22)): ['活动A13', '活动B13'],
_selectedDay.add(Duration(days: 26)): [
'活动A14',
'活动B14',
'活动C14'
],
};
_selectedEvents = _events?[_selectedDay] ?? [];
_calendarController = CalendarController();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 400),
);
_animationController.forward();
}
[@override](/user/override)
void dispose() {
_animationController.dispose();
_calendarController.dispose();
super.dispose();
}
void _onDaySelected(DateTime day, List events, List holidays) {
print('CALLBACK: _onDaySelected');
setState(() {
_selectedEvents = events;
});
}
void _onVisibleDaysChanged(
DateTime first, DateTime last, CalendarFormat format) {
print('CALLBACK: _onVisibleDaysChanged');
}
void _onCalendarCreated(
DateTime first, DateTime last, CalendarFormat format) {
print('CALLBACK: _onCalendarCreated');
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title ?? '标题'),
),
body: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
// 切换以下两行以更改TableCalendar的设置
//-----------------------
_buildTableCalendar(),
// _buildTableCalendarWithBuilders(),
const SizedBox(height: 8.0),
_buildButtons(),
const SizedBox(height: 8.0),
Expanded(child: _buildEventList()),
],
),
);
}
// 简单的TableCalendar配置(使用样式)
Widget _buildTableCalendar() {
return TableCalendar(
calendarController: _calendarController,
events: _events ?? {},
holidays: _holidays,
startingDayOfWeek: StartingDayOfWeek.monday,
calendarStyle: CalendarStyle(
selectedColor: Colors.deepOrange,
todayColor: Colors.deepOrange,
markersColor: Colors.brown,
outsideDaysVisible: false,
),
headerStyle: HeaderStyle(
formatButtonTextStyle:
TextStyle().copyWith(color: Colors.white, fontSize: 15.0),
formatButtonDecoration: BoxDecoration(
color: Colors.deepOrange[400],
borderRadius: BorderRadius.circular(16.0),
),
),
onDaySelected: _onDaySelected,
onVisibleDaysChanged: _onVisibleDaysChanged,
onCalendarCreated: _onCalendarCreated,
);
}
// 更高级的TableCalendar配置(使用构建器和样式)
/*
Widget _buildTableCalendarWithBuilders() {
return TableCalendar(
locale: 'pl_PL',
calendarController: _calendarController,
events: _events ?? {},
holidays: _holidays,
initialCalendarFormat: CalendarFormat.month,
formatAnimation: FormatAnimation.slide,
startingDayOfWeek: StartingDayOfWeek.sunday,
availableGestures: AvailableGestures.all,
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
calendarStyle: CalendarStyle(
outsideDaysVisible: false,
weekendStyle: TextStyle().copyWith(color: Colors.blue[800]),
holidayStyle: TextStyle().copyWith(color: Colors.blue[800]),
),
daysOfWeekStyle: DaysOfWeekStyle(
weekendStyle: TextStyle().copyWith(color: Colors.blue[600]),
),
headerStyle: HeaderStyle(
centerHeaderTitle: true,
formatButtonVisible: false,
),
builders: CalendarBuilders(
selectedDayBuilder: (context, date, _) {
return FadeTransition(
opacity: Tween(begin: 0.0, end: 1.0).animate(_animationController),
child: Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.deepOrange[300],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
),
);
},
todayDayBuilder: (context, date, _) {
return Container(
margin: const EdgeInsets.all(4.0),
padding: const EdgeInsets.only(top: 5.0, left: 6.0),
color: Colors.amber[400],
width: 100,
height: 100,
child: Text(
'${date.day}',
style: TextStyle().copyWith(fontSize: 16.0),
),
);
},
markersBuilder: (context, date, events, holidays) {
final children = [];
if (events.isNotEmpty) {
children.add(
Positioned(
right: 1,
bottom: 1,
child: _buildEventsMarker(date, events),
),
);
}
if (holidays.isNotEmpty) {
children.add(
Positioned(
right: -2,
top: -2,
child: _buildHolidaysMarker(),
),
);
}
return children;
},
),
onDaySelected: (date, events, holidays) {
_onDaySelected(date, events, holidays);
_animationController.forward(from: 0.0);
},
onVisibleDaysChanged: _onVisibleDaysChanged,
onCalendarCreated: _onCalendarCreated,
);
}
Widget _buildEventsMarker(DateTime date, List events) {
return AnimatedContainer(
duration: const Duration(milliseconds: 300),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: _calendarController.isSelected(date)
? Colors.brown[500]
: _calendarController.isToday(date)
? Colors.brown[300]
: Colors.blue[400],
),
width: 16.0,
height: 16.0,
child: Center(
child: Text(
'${events.length}',
style: TextStyle().copyWith(
color: Colors.white,
fontSize: 12.0,
),
),
),
);
}
Widget _buildHolidaysMarker() {
return Icon(
Icons.add_box,
size: 20.0,
color: Colors.blueGrey[800],
);
}
*/
Widget _buildButtons() {
final dateTime =
_events?.keys.elementAt((_events?.length ?? 2) - 2) ?? DateTime.now();
return Column(
children: <Widget>[
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
TextButton(
child: Text('月视图'),
onPressed: () {
setState(() {
_calendarController.setCalendarFormat(CalendarFormat.month);
});
},
),
TextButton(
child: Text('两周视图'),
onPressed: () {
setState(() {
_calendarController.setCalendarFormat(CalendarFormat.twoWeeks);
});
},
),
TextButton(
child: Text('周视图'),
onPressed: () {
setState(() {
_calendarController.setCalendarFormat(CalendarFormat.week);
});
},
),
],
),
const SizedBox(height: 8.0),
TextButton(
child: Text(
'设置日期 ${dateTime.day}-${dateTime.month}-${dateTime.year}'),
onPressed: () {
_calendarController.setSelectedDay(
DateTime(dateTime.year, dateTime.month, dateTime.day),
runCallback: true,
);
},
),
],
);
}
Widget _buildEventList() {
return ListView(
children: _selectedEvents
?.map((event) => Container(
decoration: BoxDecoration(
border: Border.all(width: 0.8),
borderRadius: BorderRadius.circular(12.0),
),
margin: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 4.0),
child: ListTile(
title: Text(event.toString()),
onTap: () => print('$event 被点击!'),
),
))
.toList() ??
[],
);
}
}
更多关于Flutter日历插件table_calendar_null_safe的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter日历插件table_calendar_null_safe的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用table_calendar_null_safe
插件的Flutter代码示例。这个插件允许你在Flutter应用中创建一个可定制的日历视图。请确保你已经在pubspec.yaml
文件中添加了依赖:
dependencies:
flutter:
sdk: flutter
table_calendar: ^3.0.0 # 请检查最新版本号
然后运行flutter pub get
来获取依赖。
以下是一个完整的示例代码,展示了如何使用table_calendar_null_safe
插件来创建一个基本的日历视图:
import 'package:flutter/material.dart';
import 'package:table_calendar/table_calendar.dart';
import 'package:intl/intl.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;
DateTime _selectedDay = DateTime.now();
Map<DateTime, List<String>> _events;
@override
void initState() {
super.initState();
_controller = CalendarController();
// 初始化事件数据
_events = {};
// 添加一些示例事件
_addEvent('2023-10-05', ['Event 1']);
_addEvent('2023-10-07', ['Event 2', 'Event 3']);
_addEvent('2023-10-15', ['Event 4']);
// 你可以根据需要添加更多事件
// 设置初始选择的日期为今天
_controller.setSelectedDay(_selectedDay, runCallback: false);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _addEvent(String date, List<String> events) {
DateTime eventDate = DateTime.parse(date);
if (!_events.containsKey(eventDate)) {
_events[eventDate] = [];
}
_events[eventDate]!.addAll(events);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Calendar Demo'),
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TableCalendar(
_controller,
locale: 'en_US',
eventLoader: _loadEvents,
startingDayOfWeek: StartingDayOfWeek.monday,
availableCalendarFormats: const {
CalendarFormat.month: '',
CalendarFormat.week: '',
},
calendarFormat: _controller.calendarFormat,
onFormatChanged: (CalendarFormat format) {
if (_controller.calendarFormat != format) {
setState(() {
_controller.calendarFormat = format;
});
}
},
onSelectedDayChanged: (DateTime day, DateTime focusedDay) {
if (focusedDay != null && focusedDay != _selectedDay) {
setState(() {
_selectedDay = focusedDay;
});
_controller.setSelectedDay(focusedDay, runCallback: false);
}
},
onCalendarCreated: (DateTime firstDay, DateTime lastDay) {
_loadEvents(firstDay, lastDay);
},
),
_buildEventList(),
],
),
),
);
}
Future<void> _loadEvents(DateTime start, DateTime end) async {
// 这里可以根据需要加载事件数据,这里为了简单起见,直接使用已有的_events数据
List<DateTime> daysWithEvents = _events.keys
.where((eventDay) => eventDay.isAfter(start.subtract(const Duration(days: 1))) && eventDay.isBefore(end.add(const Duration(days: 1))))
.toList();
// 通知控制器哪些日期有事件
_controller.setEvents(daysWithEvents);
}
Widget _buildEventList() {
return _events[_selectedDay]?.length > 0
? Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: _events[_selectedDay]!.map((event) {
return Text(
event,
style: TextStyle(decoration: TextDecoration.underline),
);
}).toList(),
),
),
)
: Container();
}
}
在这个示例中,我们创建了一个简单的日历应用,其中:
CalendarController
用于管理日历的状态。_events
字典存储了日期和事件列表的映射。_addEvent
方法用于添加事件。TableCalendar
小部件用于显示日历,并处理用户交互。_buildEventList
方法用于在选定日期下方显示事件列表。
你可以根据需要进一步自定义和扩展这个示例。