Flutter无限日历视图插件infinite_calendar_view的使用
Flutter无限日历视图插件infinite_calendar_view的使用
插件简介
infinite_calendar_view 是一个Flutter插件,允许你轻松实现所有日历UI。以下是该插件的主要特点:
- 灵感来源于Outlook和Teams移动版:易于使用。
- 三种视图:计划视图、月视图和列表视图。
- 无限滚动:懒加载,提供最佳用户体验。
- 高性能:即使每天有几十个预约也能流畅运行。
- 完全可配置:所有内容都可以自定义!
- 事件过滤:轻松过滤当天的事件。
- 事件类型管理:管理全天事件和多天事件。
- 可自定义显示天数:根据屏幕大小调整。
- 捏合缩放:用两根手指改变时间刻度。
- 拖拽功能:轻松移动预约。
- 多列支持:在同一视图中管理多个日历!
- 事件排列器:自定义安排预约的位置。
预览
Planner View
1 day | 3 days |
---|---|
7 day (web or tablet)
Month View
List View
安装
-
添加依赖到
pubspec.yaml
文件中:dependencies: infinite_calendar_view: ^最新版本号
-
执行 pub get:
flutter pub get
-
导入包:
import 'package:infinite_calendar_view/infinite_calendar_view.dart';
实现
初始化控制器
EventsController controller = EventsController();
添加日历视图
1 Day Planner View
Scaffold(
body: EventsPlanner(
controller: controller,
daysShowed: 1,
),
);
3 Days Planner View
Scaffold(
body: EventsPlanner(
controller: controller,
daysShowed: 3,
),
);
List View
Scaffold(
body: EventsList(
controller: controller,
),
);
添加或移除事件
添加事件
final event = Event(
startTime: DateTime(2024, 8, 10, 8, 0),
endTime: DateTime(2024, 8, 10, 9, 0),
title: "Event1"
);
controller.updateCalendarData((calendarData) {
calendarData.addEvents([event]);
});
添加全天事件
final fullDayEvent = FullDayEvent(
title: "Full Day Event1"
);
controller.updateCalendarData((calendarData) {
calendarData.addFullDayEvents(DateTime(2024, 8, 10), [fullDayEvent]);
});
跳转到特定日期
GlobalKey<InfiniteEventPlannerState> key = GlobalKey<InfiniteEventPlannerState>();
EventsPlanner(
key: key,
...
);
key.currentState?.jumpToDate(DateTime(2024, 8, 10));
更多功能
捏合缩放
EventsPlanner(
controller: controller,
pinchToZoomParam: PinchToZoomParameters(
pinchToZoom: true,
onZoomChange: (heightPerMinute) {},
pinchToZoomMinHeightPerMinute: 0.5,
pinchToZoomMaxHeightPerMinute: 2.5,
pinchToZoomSpeed: 1,
),
);
可拖拽事件
EventsPlanner(
controller: controller,
dayParam: DayParam(
dayEventBuilder: (event, height, width, heightPerMinute) {
return DraggableEventWidget(
event: event,
height: height,
width: width,
heightPerMinute: heightPerMinute,
onDragEnd: (exactStartDateTime, exactEndDateTime, roundStartDateTime, roundEndDateTime) {
moveEvent(event, roundStartDateTime, roundEndDateTime);
},
child: DefaultDayEvent(
height: height,
width: width,
title: event.title,
description: event.description,
),
);
},
),
);
void moveEvent(Event oldEvent, DateTime roundStartDateTime, DateTime roundEndDateTime) {
controller.updateCalendarData((calendarData) {
calendarData.updateEvent(
oldEvent: oldEvent,
newEvent: oldEvent.copyWith(
startTime: roundStartDateTime,
endTime: roundEndDateTime,
),
);
});
}
多列支持
Event(
columnIndex: 2,
...
);
EventsPlanner(
controller: controller,
columnsParam: ColumnsParam(
columns: 4,
columnsLabels: ["Tennis", "Foot", "Bad"],
columnsWidthRatio: [1 / 3, 1 / 3, 1 / 3],
columnsColors: [
Colors.yellow.pastel,
Colors.green.pastel,
Colors.blueAccent.pastel,
],
),
);
所有参数
Events Planner 参数
EventsPlanner(
key: GlobalKey<EventsPlannerState>(),
controller: controller,
daysShowed: 3,
initialDate: DateTime.now(),
maxNextDays: 365,
maxPreviousDays: 365,
heightPerMinute: 1.0,
initialVerticalScrollOffset: 1.0 * 7 * 60,
daySeparationWidth: 3,
onDayChange: (firstDay) {},
onVerticalScrollChange: (offset) {},
automaticAdjustHorizontalScrollToDay: true,
onAutomaticAdjustHorizontalScroll: (day) {},
horizontalScrollPhysics: const BouncingScrollPhysics(
decelerationRate: ScrollDecelerationRate.fast,
),
dayEventsArranger: SideEventArranger(paddingLeft: 0, paddingRight: 0),
daysHeaderParam: DaysHeaderParam(
daysHeaderVisibility: true,
daysHeaderHeight: 40.0,
daysHeaderColor: Theme.of(context).appBarTheme.backgroundColor,
dayHeaderBuilder: (day, isToday) {
return DefaultDayHeader(
dayText: DateFormat("E d").format(day),
isToday: isToday,
foregroundColor: Colors.white,
);
},
),
offTimesParam: OffTimesParam(
offTimesAllDaysRanges: [
OffTimeRange(
TimeOfDay(hour: 0, minute: 0),
TimeOfDay(hour: 7, minute: 0),
),
OffTimeRange(
TimeOfDay(hour: 18, minute: 0),
TimeOfDay(hour: 24, minute: 0),
)
],
offTimesDayRanges: {
DateTime(2024, 10, 8): [
OffTimeRange(
TimeOfDay(hour: 8, minute: 0),
TimeOfDay(hour: 18, minute: 0),
),
],
},
offTimesColor: Color(0xFFF4F4F4),
offTimesAllDaysPainter: (isToday, heightPerMinute, ranges, color) => OffSetAllDaysPainter(
isToday, heightPerMinute, [], Color(0xFFF4F4F4)),
offTimesDayPainter: (isToday, heightPerMinute, ranges, color) => OffSetAllDaysPainter(
isToday, heightPerMinute, [], Color(0xFFF4F4F4)),
),
dayParam: DayParam(
todayColor: Colors.black12,
dayTopPadding: 10,
dayBottomPadding: 15,
onSlotMinutesRound: 15,
onSlotTap: (exactDateTime, roundDateTime) {},
onSlotLongTap: (exactDateTime, roundDateTime) {},
onSlotDoubleTap: (exactDateTime, roundDateTime) {},
onDayBuild: (day) {},
dayEventBuilder: (event, height, width, heightPerMinute) {
return DefaultDayEvent(
height: height,
width: width,
title: event.title,
description: event.description,
);
},
dayCustomPainter: (heightPerMinute, isToday) => LinesPainter(
heightPerMinute: heightPerMinute,
isToday: isToday,
lineColor: Colors.black12,
),
),
fullDayParam: FullDayParam(
fullDayEventsBarVisibility: true,
fullDayEventsBarLeftText: 'All day',
fullDayEventsBarLeftWidget: Text('All day'),
fullDayEventsBarHeight: 40,
fullDayEventsBarDecoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.black12))),
),
timesIndicatorsParam: TimesIndicatorsParam(
timesIndicatorsWidth: 60.0,
timesIndicatorsHorizontalPadding: 4.0,
timesIndicatorsCustomPainter: (heightPerMinute) => HoursPainter(
heightPerMinute: 1.0,
showCurrentHour: true,
hourColor: Colors.black12,
halfHourColor: Colors.black12,
quarterHourColor: Colors.black12,
currentHourIndicatorColor: Colors.black12,
halfHourMinHeightPerMinute: 1.3,
quarterHourMinHeightPerMinute: 2,
),
),
currentHourIndicatorParam: CurrentHourIndicatorParam(
currentHourIndicatorHourVisibility: true,
currentHourIndicatorLineVisibility: true,
currentHourIndicatorColor: Colors.blue,
currentHourIndicatorCustomPainter: (heightPerMinute, isToday) =>
TimeIndicatorPainter(heightPerMinute, isToday, Colors.blue),
),
pinchToZoomParam: PinchToZoomParameters(
pinchToZoom: true,
onZoomChange: (heightPerMinute) {},
pinchToZoomMinHeightPerMinute: 0.5,
pinchToZoomMaxHeightPerMinute: 2.5,
pinchToZoomSpeed: 1,
),
);
Events List 参数
EventsList(
controller: controller,
initialDate: DateTime.now(),
maxPreviousDays: 365,
maxNextDays: 365,
onDayChange: (day) {},
todayHeaderColor: const Color(0xFFf4f9fd),
verticalScrollPhysics: const BouncingScrollPhysics(
decelerationRate: ScrollDecelerationRate.fast,
),
dayEventsBuilder: (day, events) {
return DefaultDayEvents(
events: events,
eventBuilder: (event) => DefaultDetailEvent(event: event),
nullEventsWidget: DefaultDayEvents.defaultEmptyEventsWidget,
eventSeparator: DefaultDayEvents.defaultEventSeparator,
emptyEventsWidget: DefaultDayEvents.defaultEmptyEventsWidget,
);
},
dayHeaderBuilder: (day, isToday) => DefaultHeader(
dayText: DateFormat.MMMMEEEEd().format(day).toUpperCase(),
),
);
示例代码
以下是一个完整的示例代码,展示了如何在应用中使用 infinite_calendar_view
插件:
import 'package:flutter/material.dart';
import 'package:infinite_calendar_view/infinite_calendar_view.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
EventsController eventsController = EventsController();
var calendarMode = CalendarView.day3;
var darkMode = false;
@override
void initState() {
super.initState();
eventsController.updateCalendarData((calendarData) {
// Add some sample events here
calendarData.addEvents([
Event(
startTime: DateTime.now().add(Duration(hours: 1)),
endTime: DateTime.now().add(Duration(hours: 2)),
title: "Sample Event",
),
]);
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Infinite Calendar View',
debugShowCheckedModeBanner: false,
theme: ThemeData(
useMaterial3: true,
brightness: Brightness.light,
primaryColor: Colors.blue,
appBarTheme: AppBarTheme(backgroundColor: Colors.blue),
colorScheme: ColorScheme.fromSeed(
brightness: Brightness.light,
seedColor: Colors.blue,
primary: Colors.blue,
),
),
darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
appBarTheme: AppBarTheme(backgroundColor: Color(0xff2F2F2F)),
colorScheme: ColorScheme.fromSeed(
brightness: Brightness.dark,
seedColor: Colors.blueAccent,
),
),
themeMode: darkMode ? ThemeMode.dark : ThemeMode.light,
home: Scaffold(
appBar: AppBar(
title: Text('Infinite Calendar View'),
),
body: CalendarViewWidget(
calendarMode: calendarMode,
controller: eventsController,
darkMode: darkMode),
),
);
}
}
class CalendarViewWidget extends StatelessWidget {
const CalendarViewWidget({
super.key,
required this.calendarMode,
required this.controller,
required this.darkMode,
});
final CalendarView calendarMode;
final EventsController controller;
final bool darkMode;
@override
Widget build(BuildContext context) {
return switch (calendarMode) {
CalendarView.agenda => EventsListView(
controller: controller,
),
CalendarView.day => EventsPlannerOneDayView(
key: UniqueKey(),
controller: controller,
isDarkMode: darkMode,
),
CalendarView.day3 => EventsPlannerTreeDaysView(
key: UniqueKey(),
controller: controller,
isDarkMode: darkMode,
),
CalendarView.draggableDay3 => EventsPlannerDraggableEventsView(
key: UniqueKey(),
controller: controller,
daysShowed: 3,
isDarkMode: darkMode,
),
CalendarView.day7 => EventsPlannerDraggableEventsView(
key: UniqueKey(),
controller: controller,
daysShowed: 7,
isDarkMode: darkMode,
),
CalendarView.multi_column => EventsPlannerMultiColumnView(
key: UniqueKey(),
isDarkMode: darkMode,
),
CalendarView.month => EventsMonthsView(
controller: controller,
),
};
}
}
通过上述步骤,你可以快速上手并使用 infinite_calendar_view
插件来创建功能丰富的日历视图。希望这些信息对你有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter无限日历视图插件infinite_calendar_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter无限日历视图插件infinite_calendar_view的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用infinite_calendar_view
插件来实现一个无限日历视图的示例代码。假设你已经添加了infinite_calendar_view
到你的pubspec.yaml
文件中,并且已经运行了flutter pub get
。
1. 添加依赖
首先,确保你的pubspec.yaml
文件中包含以下依赖:
dependencies:
flutter:
sdk: flutter
infinite_calendar_view: ^最新版本号 # 替换为实际的最新版本号
2. 导入插件
在你的Dart文件中导入infinite_calendar_view
:
import 'package:flutter/material.dart';
import 'package:infinite_calendar_view/infinite_calendar_view.dart';
3. 使用InfiniteCalendarView
下面是一个完整的示例,展示了如何使用InfiniteCalendarView
:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Infinite Calendar View Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: CalendarScreen(),
);
}
}
class CalendarScreen extends StatefulWidget {
@override
_CalendarScreenState createState() => _CalendarScreenState();
}
class _CalendarScreenState extends State<CalendarScreen> {
DateTime _selectedDate = DateTime.now();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Infinite Calendar View'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Selected Date: ${_selectedDate.toLocal()}',
style: TextStyle(fontSize: 20),
),
SizedBox(height: 20),
Expanded(
child: InfiniteCalendarView(
firstDayOfWeek: Day.monday,
initialSelectedDate: _selectedDate,
onDateSelected: (DateTime date) {
setState(() {
_selectedDate = date;
});
},
onDateLongPressed: (DateTime date) {
// Handle long press event if needed
print('Long pressed on: $date');
},
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
todayDecoration: BoxDecoration(
color: Colors.blue.withOpacity(0.3),
borderRadius: BorderRadius.circular(16),
),
selectedDateDecoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
),
weekdayTextStyle: TextStyle(fontSize: 14, color: Colors.grey),
dayTextStyle: TextStyle(fontSize: 16),
),
),
],
),
),
);
}
}
代码解释
- 导入必要的包:导入了
flutter/material.dart
和infinite_calendar_view
包。 - 创建应用:使用
MaterialApp
创建应用,并设置主屏幕为CalendarScreen
。 - 日历屏幕:
CalendarScreen
是一个有状态的widget,它包含一个InfiniteCalendarView
。 - 状态管理:使用
_selectedDate
变量来跟踪选中的日期,并在日期变化时更新UI。 - 日历视图:
InfiniteCalendarView
配置了各种参数,如firstDayOfWeek
、initialSelectedDate
、onDateSelected
回调等。 - 装饰:设置了日历的装饰,包括普通日期、今天和选中日期的装饰,以及星期和日期的文本样式。
这个示例提供了一个基本的无限日历视图实现,你可以根据需要进一步自定义和扩展。