Flutter连续日历插件continuous_calendar的使用
Flutter 连续日历插件 continuous_calendar 的使用
continuous_calendar
一个灵活的热图+选择器日历,可以显示多个月份,非常适合预订。
特性
目前仅支持水平布局。
开始使用
要开始使用此插件,请在 pubspec.yaml
文件中添加依赖项:
dependencies:
continuous_calendar: ^x.x.x
然后运行 flutter pub get
命令以获取最新版本的包。
使用方法
完整的示例代码可以在 /example
文件夹中查看。以下是一个简单的示例,展示如何使用 continuous_calendar
插件。
示例代码
import 'package:continuous_calendar/continuous_calendar.dart';
import 'package:date_n_time/date_n_time.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'src/material_drag_scroll_behavior.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example App',
theme: ThemeData(
useMaterial3: true,
),
home: const MyHome(),
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate
],
supportedLocales: const [
Locale('zh'), // 简体中文
],
);
}
}
class MyHome extends StatefulWidget {
const MyHome({super.key});
[@override](/user/override)
State<MyHome> createState() => _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
// LocalDate displayedMonth = LocalDate.now().atStartOfMonth();
CalendarPageController controller = CalendarPageController();
[@override](/user/override)
Widget build(BuildContext context) {
final today = LocalDate.now();
final firstDate = today.minus(2, ChronoUnit.months);
final lastDate = today.plus(2, ChronoUnit.months);
final availability = _generateAvailability();
final colorMap = availability.map((key, value) =>
MapEntry(
key,
switch (value) {
Availability.available => _colorAvailable,
Availability.blocked => _colorBlocked,
Availability.booked => _colorBooked,
Availability.unavailable => _colorUnavailable,
}));
return Scaffold(
appBar: AppBar(
title: const Text('Example App'),
actions: [
IconButton(
onPressed: () => showDateRangePicker(
context: context,
firstDate: firstDate.atStartOfDay().atZone(ZoneId.system),
lastDate: lastDate.atStartOfDay().atZone(ZoneId.system),
),
icon: const Icon(Icons.calendar_month),
),
IconButton(
onPressed: () => showDatePicker(
context: context,
firstDate: firstDate.atStartOfDay().atZone(ZoneId.system),
lastDate: lastDate.atStartOfDay().atZone(ZoneId.system),
),
icon: const Icon(Icons.calendar_today),
),
],
),
body: Column(
children: [
CalendarPageView(
firstDate: firstDate,
lastDate: lastDate,
dayBackgroundColorMap: colorMap,
rangeSelectionBackgroundColor: Colors.blue[200],
scrollBehavior: MaterialDragScrollBehavior(),
scrollDirection: Axis.horizontal,
controller: controller,
// onDisplayedMonthChanged: (date) => setState(() => displayedMonth = date),
selectableDayPredicate:
(date, selectedStartDate, selectedEndDate) =>
availability[date] == Availability.available,
),
ListenableBuilder(
listenable: controller,
builder: (context, child) {
final localizations = MaterialLocalizations.of(context);
final monthText = localizations.formatMonthYear(
controller.value.atStartOfDay().atZone(ZoneId.utc));
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: controller.previousMonth,
icon: const Icon(Icons.chevron_left),
),
Text(monthText),
IconButton(
onPressed: controller.nextMonth,
icon: const Icon(Icons.chevron_right),
),
IconButton(
onPressed: () => controller
.toMonth(controller.value.plus(2, ChronoUnit.months)),
icon: const Icon(Icons.fast_forward),
)
],
);
},
),
],
),
);
}
Map<LocalDate, Availability> _generateAvailability() {
final locale = Localizations.localeOf(context);
final today = LocalDate.now();
final startOfWeek = today.atStartOfWeek(locale.toString());
final endOfWeek = startOfWeek.plus(6, ChronoUnit.days);
final startOfNearWeek = startOfWeek.minus(1, ChronoUnit.weeks);
final endOfNearWeek = endOfWeek.plus(1, ChronoUnit.weeks);
final startOfPrevMonth = today.minus(1, ChronoUnit.months).atStartOfMonth();
final endOfNextMonth = today.plus(1, ChronoUnit.months).atEndOfMonth();
final firstDate = today.minus(2, ChronoUnit.months);
final lastDate = today.plus(2, ChronoUnit.months);
final visibleRange = LocalDateRange(firstDate, lastDate);
final totalRange = LocalDateRange(startOfPrevMonth, endOfNextMonth);
final nearRange = LocalDateRange(startOfNearWeek, endOfNearWeek);
final weekRange = LocalDateRange(startOfWeek, endOfWeek);
var visibleMap = {
for (var date in visibleRange.toLocalDates())
date: Availability.unavailable
};
var totalMap = {
for (var date in totalRange.toLocalDates()) date: Availability.available
};
var nearMap = {
for (var date in nearRange.toLocalDates()) date: Availability.blocked
};
var weekMap = {
for (var date in weekRange.toLocalDates()) date: Availability.booked
};
visibleMap
..addAll(totalMap)
..addAll(nearMap)
..addAll(weekMap);
return visibleMap;
}
static const _colorAvailable = WidgetStateColor.fromMap({
WidgetState.selected: Color(0xFF2E7D32),
WidgetState.any: Color(0xFFA5D6A7),
});
static const _colorBlocked = WidgetStateColor.fromMap({
WidgetState.selected: Color(0xFFEF6C00),
WidgetState.any: Color(0xFFFFCC80),
});
static const _colorBooked = WidgetStateColor.fromMap({
WidgetState.selected: Color(0xFFC62828),
WidgetState.any: Color(0xFFEF9A9A),
});
static const _colorUnavailable = WidgetStateColor.fromMap({
WidgetState.any: Color(0xFFE0E0E0),
});
}
enum Availability {
unavailable,
booked,
blocked,
available;
}
更多关于Flutter连续日历插件continuous_calendar的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter连续日历插件continuous_calendar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
continuous_calendar
是一个用于 Flutter 的插件,它可以帮助你实现一个连续的、自定义的日历视图。这个插件支持手势滑动、日期选择、日期范围选择等功能,适用于需要展示连续月份的日历场景。
安装插件
首先,你需要在 pubspec.yaml
文件中添加 continuous_calendar
插件的依赖:
dependencies:
flutter:
sdk: flutter
continuous_calendar: ^1.0.0 # 请使用最新的版本号
然后运行 flutter pub get
来安装插件。
基本使用
以下是一个简单的使用 continuous_calendar
插件的示例:
import 'package:flutter/material.dart';
import 'package:continuous_calendar/continuous_calendar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Continuous Calendar Example'),
),
body: ContinuousCalendar(
onMonthChanged: (DateTime date) {
print("Month changed: $date");
},
),
),
);
}
}
主要功能
-
连续滚动:默认情况下,
ContinuousCalendar
支持连续滚动,用户可以通过左右滑动来浏览不同的月份。 -
日期选择:你可以通过
onDaySelected
回调来监听用户选择的日期。ContinuousCalendar( onDaySelected: (DateTime date) { print("Selected date: $date"); }, )
-
日期范围选择:你也可以通过
onRangeSelected
回调来监听用户选择的日期范围。ContinuousCalendar( onRangeSelected: (DateTime start, DateTime end) { print("Selected range: $start - $end"); }, )
-
自定义样式:
ContinuousCalendar
提供了多种自定义选项,如calendarStyle
和headerStyle
,允许你自定义日历的外观。ContinuousCalendar( calendarStyle: CalendarStyle( selectedColor: Colors.blue, todayColor: Colors.green, ), headerStyle: HeaderStyle( titleTextStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), )
-
初始日期:你可以通过
initialDate
参数来设置日历的初始日期。ContinuousCalendar( initialDate: DateTime(2023, 10, 15), )
完整的示例
以下是一个更完整的示例,展示了如何使用 continuous_calendar
插件:
import 'package:flutter/material.dart';
import 'package:continuous_calendar/continuous_calendar.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
[@override](/user/override)
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateTime _selectedDate = DateTime.now();
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Continuous Calendar Example'),
),
body: Column(
children: [
ContinuousCalendar(
initialDate: DateTime(2023, 10, 15),
onDaySelected: (DateTime date) {
setState(() {
_selectedDate = date;
});
},
calendarStyle: CalendarStyle(
selectedColor: Colors.blue,
todayColor: Colors.green,
),
headerStyle: HeaderStyle(
titleTextStyle: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'Selected Date: $_selectedDate',
style: TextStyle(fontSize: 18),
),
),
],
),
);
}
}