Flutter日历组件插件cell_calendar的使用

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

Flutter日历组件插件cell_calendar的使用

cell_calendar

pub package License: MIT

Modern calendar widget with useful features. Enables to develop well designed calendar in a moment.

Inspired by the UI of Google Calendar

cell_calendar

使用方法

事件(Events)

你可以通过插入CalendarEvent列表作为events来在日历中显示事件。

CellCalendar(
  events: [
    CalendarEvent(eventName: "Event 1", eventDate: DateTime1),
    CalendarEvent(eventName: "Event 2", eventDate: DateTime2),
  ]
);

如果你想自定义日历,可以使用eventBackGroundColoreventTextColoreventID等额外参数。

页面改变回调(onPageChanged)

当当前页面改变时,会调用onPageChanged回调函数。

CellCalendar(
  onPageChanged: (firstDate, lastDate) {
    print("This is the first date of the new page: $firstDate");
    print("This is the last date of the new page: $lastDate");
  }
);

在这个示例代码中,firstDate是新页面最左上角单元格的日期,lastDate逻辑相同。

单元格点击回调(onCellTapped)

当用户点击一个单元格时,会调用onCellTapped回调函数。

CellCalendar(
  onCellTapped: (date) {
    print("$date is tapped !");
  }
);

它会返回被点击的DateTime,因此如果你需要的话,可以获取该日期的事件。

CellCalendar(
  onCellTapped: (date){
    print("$date is tapped !");
    final eventsOnTheDate = sampleEvents().where((event) {
      final eventDate = event.eventDate;
      return eventDate.year == date.year &&
          eventDate.month == date.month &&
          eventDate.day == date.day;
    }).toList();
    /// ex) Show dialog or navigate to new page with [eventsOnTheDate]
  }
);

自定义周标签和月份年份标签(daysOfTheWeekBuilder 和 monthYearLabelBuilder)

如果你不想使用默认的日历标签,可以通过回调函数来自定义它们。

CellCalendar(
  daysOfTheWeekBuilder: (dayIndex) {
    /// dayIndex: 0 for Sunday, 6 for Saturday.
    final labels = ["S", "M", "T", "W", "T", "F", "S"];
    return Padding(
      padding: const EdgeInsets.only(bottom: 4.0),
      child: Text(
        labels[dayIndex],
        style: TextStyle(
          fontWeight: FontWeight.bold,
        ),
        textAlign: TextAlign.center,
      ),
    );
  },
  monthYearLabelBuilder: (datetime) {
    final year = datetime.year.toString();
    final month = datetime.month.toString();
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: Text(
        "$month, $year",
        style: TextStyle(
          fontSize: 24,
          fontWeight: FontWeight.bold,
        ),
      ),
    );
  },
)

如果你有任何请求或问题,请随时在github上提问。

完整示例Demo

import 'package:cell_calendar/cell_calendar.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(title: 'cell_calendar example'),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({
    super.key,
    required this.title,
  });

  final String title;

  @override
  Widget build(BuildContext context) {
    final events = sampleEvents(); // 假设这是一个返回事件列表的方法
    final cellCalendarPageController = CellCalendarPageController();
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: CellCalendar(
        cellCalendarPageController: cellCalendarPageController,
        events: events,
        daysOfTheWeekBuilder: (dayIndex) {
          final labels = ["S", "M", "T", "W", "T", "F", "S"];
          return Padding(
            padding: const EdgeInsets.only(bottom: 4.0),
            child: Text(
              labels[dayIndex],
              style: const TextStyle(
                fontWeight: FontWeight.bold,
              ),
              textAlign: TextAlign.center,
            ),
          );
        },
        monthYearLabelBuilder: (datetime) {
          final year = datetime!.year.toString();
          final month = datetime.month.monthName; // 注意:这里假设有一个扩展方法 monthName
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 4),
            child: Row(
              children: [
                const SizedBox(width: 16),
                Text(
                  "$month  $year",
                  style: const TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const Spacer(),
                IconButton(
                  padding: EdgeInsets.zero,
                  icon: const Icon(Icons.calendar_today),
                  onPressed: () {
                    cellCalendarPageController.animateToDate(
                      DateTime.now(),
                      curve: Curves.linear,
                      duration: const Duration(milliseconds: 300),
                    );
                  },
                )
              ],
            ),
          );
        },
        onCellTapped: (date) {
          final eventsOnTheDate = events.where((event) {
            final eventDate = event.eventDate;
            return eventDate.year == date.year &&
                eventDate.month == date.month &&
                eventDate.day == date.day;
          }).toList();
          showDialog(
              context: context,
              builder: (_) => AlertDialog(
                    title: Text("${date.month.monthName} ${date.day}"),
                    content: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: eventsOnTheDate
                          .map(
                            (event) => Container(
                              width: double.infinity,
                              padding: const EdgeInsets.all(4),
                              margin: const EdgeInsets.only(bottom: 12),
                              color: event.eventBackgroundColor,
                              child: Text(
                                event.eventName,
                                style: event.eventTextStyle,
                              ),
                            ),
                          )
                          .toList(),
                    ),
                  ));
        },
        onPageChanged: (firstDate, lastDate) {
          /// Called when the page was changed
          /// Fetch additional events by using the range between [firstDate] and [lastDate] if you want
        },
      ),
    );
  }
}

这个完整的示例展示了如何创建一个包含自定义标签、事件显示、页面切换回调以及单元格点击弹出对话框的应用程序。请确保你已经正确导入了所有必要的包,并且根据你的需求调整了sampleEvents()方法以提供测试数据。


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用cell_calendar插件的示例代码。cell_calendar是一个功能强大的日历组件,适用于需要显示和操作日历数据的场景。

首先,确保你已经在pubspec.yaml文件中添加了cell_calendar依赖:

dependencies:
  flutter:
    sdk: flutter
  cell_calendar: ^最新版本号  # 替换为实际的最新版本号

然后运行flutter pub get来获取依赖。

接下来是一个简单的示例,展示如何使用cell_calendar来显示一个基本的日历:

import 'package:flutter/material.dart';
import 'package:cell_calendar/cell_calendar.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Calendar Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CalendarPage(),
    );
  }
}

class CalendarPage extends StatefulWidget {
  @override
  _CalendarPageState createState() => _CalendarPageState();
}

class _CalendarPageState extends State<CalendarPage> {
  final List<DateTime> selectedDates = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Calendar Example'),
      ),
      body: CellCalendar(
        // 初始化日期,默认为当前日期
        initDate: DateTime.now(),
        // 标记日期的点击事件
        onDateSelected: (date, state) {
          setState(() {
            if (state) {
              selectedDates.add(date);
            } else {
              selectedDates.remove(date);
            }
          });
        },
        // 自定义日期单元格
        dateCellBuilder: (context, date, state) {
          return Container(
            alignment: Alignment.center,
            decoration: BoxDecoration(
              color: state && selectedDates.contains(date)
                  ? Colors.blue.withOpacity(0.3)
                  : null,
              border: Border.all(
                color: state ? Colors.blue : Colors.transparent,
              ),
            ),
            child: Text(
              '${date.day}',
              style: TextStyle(
                color: state ? Colors.blue : Colors.black,
                fontSize: 16.0,
              ),
            ),
          );
        },
        // 自定义月份头部
        monthHeaderBuilder: (context, year, month) {
          return Padding(
            padding: EdgeInsets.only(top: 10.0, bottom: 5.0),
            child: Text(
              '${year}年${month}月',
              style: TextStyle(
                fontSize: 18.0,
                fontWeight: FontWeight.bold,
              ),
            ),
          );
        },
        // 自定义星期头部
        weekHeaderBuilder: (context, day) {
          return Text(
            day.substring(0, 1).toUpperCase(),
            style: TextStyle(
              fontSize: 14.0,
              color: Colors.grey,
            ),
          );
        },
      ),
    );
  }
}

在这个示例中:

  1. CellCalendar组件用于显示日历。
  2. initDate属性设置初始日期为当前日期。
  3. onDateSelected回调函数用于处理日期选择事件,当用户点击某个日期时,会触发此回调。
  4. dateCellBuilder属性允许自定义日期单元格的显示,你可以根据日期是否被选中来设置不同的样式。
  5. monthHeaderBuilderweekHeaderBuilder属性分别用于自定义月份和星期的头部显示。

这个示例展示了如何使用cell_calendar来创建一个基本的日历,并自定义日期单元格和头部。你可以根据自己的需求进一步扩展和修改这个示例。

回到顶部