Flutter日历展示插件sliver_calendar的使用

Flutter日历展示插件sliver_calendar的使用

sliver_calendar 是一个用于在 Flutter 中展示滚动日历列表的插件。它允许用户通过滑动浏览事件,并支持自定义日历头部和月份头部的背景图片。尽管功能相对基础,但它已经能够正常工作。

日历使用 Slivers 来展示视图中的小部件,并允许用户向前或向后滚动事件。头部小部件会根据需要展开,显示当月的日期,让用户可以选择特定日期并切换月份。默认情况下,它显示的是事件列表而不是日视图,日视图的相关代码目前还只是一个占位符。

如何使用 CalendarWidget

以下是如何直接使用 CalendarWidget 的示例:

new CalendarWidget(
  initialDate: new TZDateTime.now(local),
  buildItem: buildItem,
  getEvents: getEvents,
);

设置日历数据源

以下是为 CalendarWidget 设置数据源的示例代码:

List<Game> _listToShow;
StreamSubscription<UpdateReason> _listening;

@override
Widget buildItem(BuildContext context, CalendarEvent event) {
  return new GameCard(_listToShow[event.index]);
}

@override
List<CalendarEvent> getEvents(DateTime start, DateTime end) {
  if (_listToShow == null) {
    _listToShow = UserDatabaseData.instance.games.values.toList();
  }
  if (_listToShow == null) {
    return [];
  }
  List<CalendarEvent> events = new List<CalendarEvent>();
  int pos = 0;
  _listToShow.forEach((Game g) => events.add(new CalendarEvent(
      instant: g.tzTime, instantEnd: g.tzEndTime, index: pos++)));
  return events;
}

日历运行效果

以下是日历的实际运行效果:

日历展示

开始使用

初始化项目

确保你已经安装了 Flutter 和 Dart 环境,并创建了一个新的 Flutter 项目。然后,在 pubspec.yaml 文件中添加 sliver_calendar 依赖:

dependencies:
  sliver_calendar: ^版本号

运行 flutter pub get 安装依赖。

示例代码

以下是一个完整的示例代码,展示了如何在 Flutter 应用中集成 sliver_calendar 插件:

import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_native_timezone/flutter_native_timezone.dart';
import 'package:sliver_calendar/sliver_calendar.dart';
import 'package:timezone/timezone.dart';
import 'package:timezone/data/latest_all.dart' if (kIsWeb) 'package:timezone/browser.dart' as tz;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (kIsWeb) {
    tz.initializeTimeZones();
  } else {
    tz.initializeTimeZones();
  }

  var localTimeZone = await FlutterNativeTimezone.getLocalTimezone();
  if (localTimeZone == 'Etc/UTC') {}

  var loc = getLocation(localTimeZone);
  runApp(MyApp(loc));
}

class MyApp extends StatelessWidget {
  final Location loc;

  MyApp(this.loc);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Calendar',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate
      ],
      supportedLocales: const [
        Locale('en', ''),
        Locale('fr', ''),
      ],
      home: MyHomePage(title: 'Flutter Calendar demo', loc: loc),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title, required this.loc})
      : super(key: key);
  final String title;
  final Location loc;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<CalendarEvent> events = [];
  Random random = Random();
  TZDateTime nowDate = TZDateTime.utc(2021);

  @override
  void initState() {
    super.initState();
    nowDate = TZDateTime.now(widget.loc);
  }

  Widget buildItem(BuildContext context, CalendarEvent e) {
    return Card(
      child: ListTile(
        title: Text("Event ${e.index}"),
        subtitle: Text("Yay for events"),
        leading: const Icon(Icons.gamepad),
      ),
    );
  }

  List<CalendarEvent> getEvents(DateTime start, DateTime end) {
    if (events.isEmpty) {
      TZDateTime nowTime =
          TZDateTime.now(widget.loc).subtract(Duration(days: 5));
      for (int i = 0; i < 20; i++) {
        TZDateTime start = nowTime.add(Duration(days: i + random.nextInt(10)));
        events.add(CalendarEvent(
            index: i,
            instant: start,
            instantEnd: start.add(Duration(minutes: 30))));
      }
    }
    return events;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(children: [
        Expanded(
          child: CalendarWidget(
            initialDate: nowDate,
            location: widget.loc,
            buildItem: buildItem,
            getEvents: getEvents,
            bannerHeader: AssetImage("assets/images/calendarheader.png"),
            monthHeader: AssetImage("assets/images/calendarbanner.jpg"),
            weekBeginsWithDay: 1, // Sunday = 0, Monday = 1, ..., Saturday = 6
          ),
        ),
      ]),
    );
  }
}

代码说明

  1. 初始化时间区

    WidgetsFlutterBinding.ensureInitialized();
    if (kIsWeb) {
      tz.initializeTimeZones();
    } else {
      tz.initializeTimeZones();
    }
    

    初始化时区支持,确保插件能正确处理时间相关的逻辑。

  2. 构建事件列表

    List<CalendarEvent> getEvents(DateTime start, DateTime end) {
      if (events.isEmpty) {
        TZDateTime nowTime = TZDateTime.now(widget.loc).subtract(Duration(days: 5));
        for (int i = 0; i < 20; i++) {
          TZDateTime start = nowTime.add(Duration(days: i + random.nextInt(10)));
          events.add(CalendarEvent(
              index: i,
              instant: start,
              instantEnd: start.add(Duration(minutes: 30))));
        }
      }
      return events;
    }
    

    模拟生成 20 个随机事件,每个事件持续 30 分钟。

  3. 渲染事件卡片

    Widget buildItem(BuildContext context, CalendarEvent e) {
      return Card(
        child: ListTile(
          title: Text("Event ${e.index}"),
          subtitle: Text("Yay for events"),
          leading: const Icon(Icons.gamepad),
        ),
      );
    }
    

    使用 CardListTile 渲染每个事件。

  4. 日历组件

    CalendarWidget(
      initialDate: nowDate,
      location: widget.loc,
      buildItem: buildItem,
      getEvents: getEvents,
      bannerHeader: AssetImage("assets/images/calendarheader.png"),
      monthHeader: AssetImage("assets/images/calendarbanner.jpg"),
      weekBeginsWithDay: 1,
    )
    

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

1 回复

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


sliver_calendar 是一个用于 Flutter 的日历展示插件,它允许你在应用中使用 Sliver 组件来展示日历。这个插件非常适合需要将日历嵌入到 CustomScrollView 或其他 Sliver 组件的应用中。

安装

首先,你需要在 pubspec.yaml 文件中添加 sliver_calendar 依赖:

dependencies:
  flutter:
    sdk: flutter
  sliver_calendar: ^1.0.0  # 请检查最新版本

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

基本用法

以下是一个简单的示例,展示如何使用 sliver_calendar 插件来展示一个日历:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: CustomScrollView(
          slivers: <Widget>[
            SliverAppBar(
              title: Text('Sliver Calendar Example'),
              expandedHeight: 200.0,
              flexibleSpace: FlexibleSpaceBar(
                background: Image.network(
                  'https://via.placeholder.com/150',
                  fit: BoxFit.cover,
                ),
              ),
            ),
            SliverCalendar(
              initialDate: DateTime.now(),
              onDateSelected: (date) {
                print('Selected date: $date');
              },
            ),
          ],
        ),
      ),
    );
  }
}

参数说明

  • initialDate: 初始显示的日期,默认为当前日期。
  • onDateSelected: 当用户选择日期时的回调函数。
  • firstDate: 可选参数,设置日历中最早可选的日期。
  • lastDate: 可选参数,设置日历中最晚可选的日期。
  • selectedDate: 可选参数,设置当前选中的日期。
  • headerStyle: 可选参数,自定义日历头部的样式。
  • dayBuilder: 可选参数,自定义日历中每一天的展示方式。

自定义日历样式

你可以通过 dayBuilder 参数来自定义日历中每一天的展示方式。例如:

SliverCalendar(
  initialDate: DateTime.now(),
  onDateSelected: (date) {
    print('Selected date: $date');
  },
  dayBuilder: (context, date, isSelected, isToday) {
    return Container(
      decoration: BoxDecoration(
        color: isSelected ? Colors.blue : (isToday ? Colors.green : null),
        shape: BoxShape.circle,
      ),
      child: Center(
        child: Text(
          date.day.toString(),
          style: TextStyle(
            color: isSelected ? Colors.white : (isToday ? Colors.white : Colors.black),
          ),
        ),
      ),
    );
  },
)
回到顶部