Flutter日历功能插件mobkit_calendar的使用

发布于 1周前 作者 eggper 来自 Flutter

Flutter日历功能插件mobkit_calendar的使用

Mobkit Calendar简介

Mobkit Calendar 是一个功能强大的Flutter日历插件,它内置了多种可配置视图,如日视图、周视图、月视图和时间线日视图,这些视图为计划和展示预约/事件提供了高效的基础功能。以下是其主要特点:

技术特性

  • 可定制的日历视图:通过多种视图和特殊选项轻松实现所需外观。
  • 预约:包含关于特定时间安排的事件或会议的信息,具有许多可自定义字段,如开始/结束时间、事件标题、事件详情和颜色。
  • 重复预约:支持每日、每周和每月的重复预约,并可以添加重复规则以在长时间范围内重复安排预约。
  • 时区:允许根据所需的时区配置事件,而不论设备上的时间如何。

视图

  • 月视图
    • 分数视图
    • 全屏视图
    • 弹出视图
  • 周视图
    • 全天事件
    • 短事件
  • 日视图
    • 全天事件
    • 短事件
  • 议程视图

原生日历

Mobkit Calendar 提供了与本地日历交互的功能:

  • requestCalendarAccess:提示用户授权访问本地日历。
  • getEventList:根据给定的日历ID返回日历中的事件列表。
  • getAccountList:返回设备上可用的本地日历账户列表。
  • openEventDetail:在本地日历中打开相关事件的详细信息。

预约

预约允许用户定义带有特定时间段、重复模式和各种自定义设置的事件/预约。例如:

  • nativeEventId:如果相关事件是原生事件,则返回其ID。
  • title:事件标题。
  • appointmentStartDateappointmentEndDate:事件的开始时间和结束时间。
  • color:事件的颜色(如果有)。
  • isAllDay:是否为全天事件。
  • detail:事件详情。
  • recurrenceModel:事件的重复模式(如果有)。
  • eventData:创建事件时附加的对象。

参数

MobkitCalendarConfigModel 包含了大量的配置参数,用于定制日历的各个方面,如显示样式、颜色、动画等。具体参数请参阅内容部分

示例代码

以下是一个完整的示例代码,展示了如何使用 mobkit_calendar 插件创建一个包含四种视图(月视图、周视图、日视图和议程视图)的日历应用。

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:mobkit_calendar/mobkit_calendar.dart';

void main() {
  runApp(const MyApp());
}

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

double pageHeight = MediaQuery.of(navigatorKey.currentContext!).size.height;
double pageWidht = MediaQuery.of(navigatorKey.currentContext!).size.width;

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  late TabController _tabController;

  MobkitCalendarConfigModel getConfig(MobkitCalendarViewType mobkitCalendarViewType) {
    return MobkitCalendarConfigModel(
      cellConfig: CalendarCellConfigModel(
        disabledStyle: CalendarCellStyle(
          textStyle: TextStyle(fontSize: 14, color: Colors.grey.withOpacity(0.5)),
          color: Colors.transparent,
        ),
        enabledStyle: CalendarCellStyle(
          textStyle: const TextStyle(fontSize: 14, color: Colors.black),
          border: Border.all(color: Colors.grey.withOpacity(0.2), width: 1),
        ),
        selectedStyle: CalendarCellStyle(
          color: Colors.orange,
          textStyle: const TextStyle(fontSize: 14, color: Colors.white),
          border: Border.all(color: Colors.black, width: 1),
        ),
        currentStyle: CalendarCellStyle(
          textStyle: const TextStyle(color: Colors.lightBlue),
        ),
      ),
      calendarPopupConfigModel: CalendarPopupConfigModel(
        popUpBoxDecoration: const BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(25))),
        popUpOpacity: true,
        animateDuration: 500,
        verticalPadding: 30,
        popupSpace: 10,
        popupHeight: MediaQuery.of(context).size.height * 0.6,
        popupWidth: MediaQuery.of(context).size.width,
        viewportFraction: 0.9,
      ),
      topBarConfig: CalendarTopBarConfigModel(
        isVisibleHeaderWidget:
            mobkitCalendarViewType == MobkitCalendarViewType.monthly ||
                mobkitCalendarViewType == MobkitCalendarViewType.agenda,
        isVisibleTitleWidget: true,
        isVisibleMonthBar: false,
        isVisibleYearBar: false,
        isVisibleWeekDaysBar: true,
        weekDaysStyle: const TextStyle(fontSize: 14, color: Colors.black),
      ),
      weekDaysBarBorderColor: Colors.transparent,
      locale: "en",
      disableOffDays: true,
      disableWeekendsDays: false,
      monthBetweenPadding: 20,
      primaryColor: Colors.lightBlue,
      popupEnable: mobkitCalendarViewType == MobkitCalendarViewType.monthly
          ? true
          : false,
    );
  }

  @override
  void initState() {
    _tabController = TabController(length: 4, vsync: this);
    super.initState();
  }

  List<MobkitCalendarAppointmentModel> eventList = [
    MobkitCalendarAppointmentModel(
      title: "Recurring event every 2 days (10 repetitions)",
      appointmentStartDate: DateTime.now().add(const Duration(days: -1)),
      appointmentEndDate: DateTime.now(),
      isAllDay: true,
      color: Colors.red,
      detail: "Recurring event every 2 days (10 repetitions)",
      recurrenceModel: RecurrenceModel(
          endDate: DateTime.now().add(const Duration(days: 500)),
          frequency: DailyFrequency(),
          interval: 10,
          repeatOf: 2),
    ),
    // ... 其他事件 ...
  ];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      navigatorKey: navigatorKey,
      scrollBehavior: const MaterialScrollBehavior().copyWith(
        dragDevices: {
          PointerDeviceKind.mouse,
          PointerDeviceKind.touch,
          PointerDeviceKind.stylus,
          PointerDeviceKind.unknown
        },
      ),
      home: Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.transparent,
          elevation: 0,
          title: const Text("Mobkit Calendar"),
          bottom: TabBar(
            controller: _tabController,
            padding: EdgeInsets.zero,
            tabs: const <Widget>[
              Tab(text: "Monthly"),
              Tab(text: "Weekly"),
              Tab(text: "Daily"),
              Tab(text: "Agenda"),
            ],
          ),
        ),
        body: TabBarView(
          controller: _tabController,
          physics: const NeverScrollableScrollPhysics(),
          children: [
            // Monthly View
            MobkitCalendarWidget(
              minDate: DateTime(1800),
              key: UniqueKey(),
              config: getConfig(MobkitCalendarViewType.monthly),
              dateRangeChanged: (datetime) => null,
              headerWidget: (models, datetime) => HeaderWidget(
                datetime: datetime,
                models: models,
              ),
              titleWidget: (models, datetime) => TitleWidget(
                datetime: datetime,
                models: models,
              ),
              onSelectionChange: (models, date) => null,
              eventTap: (model) => null,
              onPopupWidget: (models, datetime) => OnPopupWidget(
                datetime: datetime,
                models: models,
              ),
              onDateChanged: (datetime) => null,
              mobkitCalendarController: MobkitCalendarController(
                viewType: MobkitCalendarViewType.monthly,
                appointmentList: eventList,
              ),
            ),
            // Weekly View
            MobkitCalendarWidget(
              minDate: DateTime(1800),
              key: UniqueKey(),
              config: getConfig(MobkitCalendarViewType.weekly),
              dateRangeChanged: (datetime) => null,
              headerWidget: (models, datetime) => HeaderWidget(
                datetime: datetime,
                models: models,
              ),
              weeklyViewWidget: (val) => Expanded(
                child: ListView.builder(
                  itemCount: val.length,
                  itemBuilder: (context, index) {
                    DateTime dateTime = val.keys.elementAt(index);
                    return val[dateTime] != null
                        ? Padding(
                            padding: const EdgeInsets.all(12),
                            child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    DateFormat("dd MMMM").format(dateTime),
                                  ),
                                  const SizedBox(height: 6),
                                  val[dateTime]!.isNotEmpty
                                      ? SizedBox(
                                          height: val[dateTime]!.length * 45,
                                          child: ListView.builder(
                                            itemCount: val[dateTime]!.length,
                                            physics: const NeverScrollableScrollPhysics(),
                                            itemBuilder: (context, i) {
                                              return GestureDetector(
                                                child: Column(
                                                  children: [
                                                    Row(
                                                      children: [
                                                        Container(
                                                          height: 40,
                                                          color: val[dateTime]![i].color,
                                                          width: 3,
                                                        ),
                                                        const SizedBox(width: 12),
                                                        Flexible(
                                                          child: Text(
                                                            val[dateTime]![i].title ?? "",
                                                            overflow: TextOverflow.ellipsis,
                                                            maxLines: 1,
                                                          ),
                                                        ),
                                                      ],
                                                    ),
                                                    const SizedBox(height: 4),
                                                  ],
                                                ),
                                              );
                                            },
                                          ),
                                        )
                                      : Container(),
                                ]),
                          )
                        : Container();
                  },
                ),
              ),
              titleWidget: (models, datetime) => TitleWidget(
                datetime: datetime,
                models: models,
              ),
              onSelectionChange: (models, date) => null,
              eventTap: (model) => null,
              onPopupWidget: (models, datetime) => OnPopupWidget(
                datetime: datetime,
                models: models,
              ),
              onDateChanged: (datetime) => null,
              mobkitCalendarController: MobkitCalendarController(
                viewType: MobkitCalendarViewType.weekly,
                appointmentList: eventList,
              ),
            ),
            // Daily View
            MobkitCalendarWidget(
              minDate: DateTime(1800),
              key: UniqueKey(),
              config: getConfig(MobkitCalendarViewType.daily),
              dateRangeChanged: (datetime) => null,
              headerWidget: (models, datetime) => HeaderWidget(
                datetime: datetime,
                models: models,
              ),
              titleWidget: (models, datetime) => TitleWidget(
                datetime: datetime,
                models: models,
              ),
              onSelectionChange: (models, date) => null,
              eventTap: (model) => null,
              onPopupWidget: (models, datetime) => OnPopupWidget(
                datetime: datetime,
                models: models,
              ),
              onDateChanged: (datetime) => null,
              mobkitCalendarController: MobkitCalendarController(
                viewType: MobkitCalendarViewType.daily,
                appointmentList: eventList,
              ),
            ),
            // Agenda View
            MobkitCalendarWidget(
              minDate: DateTime(1800),
              key: UniqueKey(),
              config: getConfig(MobkitCalendarViewType.agenda),
              dateRangeChanged: (datetime) => null,
              headerWidget: (models, datetime) => HeaderWidget(
                datetime: datetime,
                models: models,
              ),
              titleWidget: (models, datetime) => TitleWidget(
                datetime: datetime,
                models: models,
              ),
              onSelectionChange: (models, date) => null,
              eventTap: (model) => null,
              onPopupWidget: (models, datetime) => OnPopupWidget(
                datetime: datetime,
                models: models,
              ),
              onDateChanged: (datetime) => null,
              mobkitCalendarController: MobkitCalendarController(
                viewType: MobkitCalendarViewType.agenda,
                appointmentList: eventList,
              ),
            )
          ],
        ),
      ),
    );
  }
}

// Popup widget for events
class OnPopupWidget extends StatelessWidget {
  const OnPopupWidget({
    super.key,
    required this.datetime,
    required this.models,
  });

  final DateTime datetime;
  final List<MobkitCalendarAppointmentModel> models;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 18),
      child: models.isNotEmpty
          ? Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8),
                  child: Text(
                    DateFormat("EEE, MMMM d").format(datetime),
                    style: const TextStyle(fontSize: 18, color: Colors.grey),
                  ),
                ),
                const Divider(thickness: 1, color: Colors.grey),
                Expanded(
                  child: ListView.builder(
                    itemCount: models.length,
                    physics: const NeverScrollableScrollPhysics(),
                    itemBuilder: (context, index) {
                      return GestureDetector(
                        onTap: () {},
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 2),
                          child: Row(children: [
                            Container(
                              height: 40,
                              color: models[index].color,
                              width: 3,
                            ),
                            const SizedBox(width: 12),
                            Flexible(
                              child: Text(
                                models[index].title ?? "",
                                overflow: TextOverflow.ellipsis,
                                maxLines: 1,
                                style: const TextStyle(fontSize: 14, color: Colors.grey),
                              ),
                            ),
                          ]),
                        ),
                      );
                    },
                  ),
                ),
              ],
            )
          : Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 8),
                  child: Text(
                    DateFormat("EEE, MMMM d").format(datetime),
                    style: const TextStyle(fontSize: 18, color: Colors.grey),
                  ),
                ),
                const Divider(thickness: 1, color: Colors.grey),
              ],
            ),
    );
  }
}

// Title widget for the calendar
class TitleWidget extends StatelessWidget {
  const TitleWidget({
    super.key,
    required this.datetime,
    required this.models,
  });

  final DateTime datetime;
  final List<MobkitCalendarAppointmentModel> models;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 12),
      child: Column(children: [
        Text(
          DateFormat("yyyy MMMM").format(datetime),
          style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold, color: Colors.black),
        ),
      ]),
    );
  }
}

// Header widget for the calendar
class HeaderWidget extends StatelessWidget {
  const HeaderWidget({
    super.key,
    required this.datetime,
    required this.models,
  });

  final DateTime datetime;
  final List<MobkitCalendarAppointmentModel> models;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 12),
      child: Column(children: [
        Text(
          DateFormat("MMMM").format(datetime),
          style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500, color: Colors.black54),
        ),
      ]),
    );
  }
}

这个示例展示了如何创建一个包含四种不同视图的日历应用,并且每个视图都配置了不同的样式和行为。你可以根据需要调整配置参数以满足具体需求。希望这能帮助你更好地理解和使用 mobkit_calendar 插件!


更多关于Flutter日历功能插件mobkit_calendar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter日历功能插件mobkit_calendar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用mobkit_calendar插件来实现日历功能的代码示例。mobkit_calendar是一个功能强大的Flutter日历插件,支持多种日历视图和事件管理。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加mobkit_calendar依赖:

dependencies:
  flutter:
    sdk: flutter
  mobkit_calendar: ^最新版本号  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 导入插件

在你的Dart文件中导入mobkit_calendar

import 'package:mobkit_calendar/mobkit_calendar.dart';

3. 使用MobkitCalendar组件

下面是一个简单的示例,展示如何在Flutter应用中使用MobkitCalendar组件:

import 'package:flutter/material.dart';
import 'package:mobkit_calendar/mobkit_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: CalendarScreen(),
    );
  }
}

class CalendarScreen extends StatefulWidget {
  @override
  _CalendarScreenState createState() => _CalendarScreenState();
}

class _CalendarScreenState extends State<CalendarScreen> {
  final List<EventModel> events = [
    EventModel(
      date: DateTime(2023, 10, 5),
      title: 'Event 1',
      color: Colors.red,
    ),
    EventModel(
      date: DateTime(2023, 10, 10),
      title: 'Event 2',
      color: Colors.blue,
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Calendar Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: MobkitCalendar(
          // 配置日历
          selectedDate: DateTime.now(),
          firstDayOfWeek: 1,  // 周一作为一周的第一天
          events: events,
          onEventClicked: (event) {
            // 点击事件回调
            showDialog(
              context: context,
              builder: (context) => AlertDialog(
                title: Text(event.title),
                content: Text('Date: ${event.date.toLocal()}'),
                actions: [
                  TextButton(
                    onPressed: () => Navigator.of(context).pop(),
                    child: Text('OK'),
                  ),
                ],
              ),
            );
          },
          onDateSelected: (date) {
            // 选择日期回调
            print('Selected date: $date');
          },
          // 其他配置...
        ),
      ),
    );
  }
}

// 事件模型
class EventModel {
  DateTime date;
  String title;
  Color color;

  EventModel({required this.date, required this.title, required this.color});
}

4. 运行应用

将上述代码添加到你的Flutter项目中,然后运行应用。你应该会看到一个带有事件标记的日历,点击事件会弹出一个对话框显示事件详情,选择日期会在控制台打印所选日期。

这个示例展示了如何快速集成mobkit_calendar插件,并通过简单的配置和事件回调来处理日历的交互。你可以根据需求进一步自定义和扩展这个基础示例。

回到顶部