Flutter日历展示插件table_calendar的使用

Flutter日历展示插件table_calendar的使用

TableCalendar

Pub Package Awesome Flutter

TableCalendar是一个高度可定制、功能丰富的Flutter日历组件。

特性 描述
Image TableCalendar with custom styles
Image TableCalendar with custom builders

Features

  • 简单易用的API
  • 可自定义样式的预配置UI
  • 支持自定义构建器以实现无限UI设计
  • 支持多语言
  • 支持范围选择和多选
  • 动态事件和节日
  • 垂直自动调整大小,适应内容或填充视口
  • 多种日历格式(月、两周、周)
  • 水平滑动边界(第一天、最后一天)

Usage

Installation

pubspec.yaml中添加以下依赖:

dependencies:
  table_calendar: ^3.2.0

Basic Setup

完整的示例代码可以在这里找到。

初始化TableCalendar

TableCalendar(
  firstDay: DateTime.utc(2010, 10, 16),
  lastDay: DateTime.utc(2030, 3, 14),
  focusedDay: DateTime.now(),
);
  • firstDay:日历最早可访问的日期。
  • lastDay:日历最晚可访问的日期。
  • focusedDay:当前聚焦的日期。

添加交互性

为了让日历响应用户的点击操作,并标记选中的日期,可以添加以下回调函数:

selectedDayPredicate: (day) {
  return isSameDay(_selectedDay, day);
},
onDaySelected: (selectedDay, focusedDay) {
  setState(() {
    _selectedDay = selectedDay;
    _focusedDay = focusedDay; // 更新 `_focusedDay`
  });
},

为了动态更新可见的日历格式,可以添加以下代码:

calendarFormat: _calendarFormat,
onFormatChanged: (format) {
  setState(() {
    _calendarFormat = format;
  });
},

更新focusedDay

为了避免每次热重载时日历回到初始状态,需要更新focusedDay

onPageChanged: (focusedDay) {
  _focusedDay = focusedDay;
},

Events

完整的事件示例代码可以在这里找到。

可以通过eventLoader属性为TableCalendar提供自定义事件:

eventLoader: (day) {
  return _getEventsForDay(day);
},

例如,使用LinkedHashMap来存储事件:

final events = LinkedHashMap(
  equals: isSameDay,
  hashCode: getHashCode,
)..addAll(eventSource);

List<Event> _getEventsForDay(DateTime day) {
  return events[day] ?? [];
}

循环事件

通过eventLoader可以轻松添加循环事件。例如,每周一添加一个事件:

eventLoader: (day) {
  if (day.weekday == DateTime.monday) {
    return [Event('Cyclic event')];
  }
  return [];
},

选中事件

当用户点击某天时,获取该天的事件列表:

void _onDaySelected(DateTime selectedDay, DateTime focusedDay) {
  if (!isSameDay(_selectedDay, selectedDay)) {
    setState(() {
      _focusedDay = focusedDay;
      _selectedDay = selectedDay;
      _selectedEvents = _getEventsForDay(selectedDay);
    });
  }
}

Custom UI with CalendarBuilders

通过CalendarBuilders可以自定义UI。例如,只覆盖周日的标签:

calendarBuilders: CalendarBuilders(
  dowBuilder: (context, day) {
    if (day.weekday == DateTime.sunday) {
      final text = DateFormat.E().format(day);
      return Center(
        child: Text(
          text,
          style: TextStyle(color: Colors.red),
        ),
      );
    }
  },
),

Locale

通过locale属性设置日历的语言。例如,设置为波兰语:

TableCalendar(
  locale: 'pl_PL',
),

初始化

如果需要使用其他语言,首先需要初始化日期格式化:

import 'package:intl/date_symbol_data_local.dart';

void main() {
  initializeDateFormatting().then((_) => runApp(MyApp()));
}

示例代码

以下是main.dart的完整示例代码:

import 'package:flutter/material.dart';
import 'package:intl/date_symbol_data_local.dart';
import 'package:table_calendar_example/pages/basics_example.dart';
import 'package:table_calendar_example/pages/complex_example.dart';
import 'package:table_calendar_example/pages/events_example.dart';
import 'package:table_calendar_example/pages/multi_example.dart';
import 'package:table_calendar_example/pages/range_example.dart';

void main() {
  initializeDateFormatting().then((_) => runApp(const MyApp()));
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TableCalendar Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const StartPage(),
    );
  }
}

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

  @override
  State<StartPage> createState() => _StartPageState();
}

class _StartPageState extends State<StartPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TableCalendar Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const SizedBox(height: 20.0),
            ElevatedButton(
              child: const Text('Basics'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => const TableBasicsExample()),
              ),
            ),
            const SizedBox(height: 12.0),
            ElevatedButton(
              child: const Text('Range Selection'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => const TableRangeExample()),
              ),
            ),
            const SizedBox(height: 12.0),
            ElevatedButton(
              child: const Text('Events'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => const TableEventsExample()),
              ),
            ),
            const SizedBox(height: 12.0),
            ElevatedButton(
              child: const Text('Multiple Selection'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => const TableMultiExample()),
              ),
            ),
            const SizedBox(height: 12.0),
            ElevatedButton(
              child: const Text('Complex'),
              onPressed: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => const TableComplexExample()),
              ),
            ),
            const SizedBox(height: 20.0),
          ],
        ),
      ),
    );
  }
}

希望这些信息能帮助你更好地理解和使用table_calendar插件!如果有任何问题或需要进一步的帮助,请随时提问。

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用table_calendar插件来展示日历的示例代码。这个示例将展示如何集成table_calendar插件,并处理日历的选择事件。

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

dependencies:
  flutter:
    sdk: flutter
  table_calendar: ^3.0.5  # 请检查最新版本号

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

接下来,在你的Flutter项目中创建一个展示日历的页面。以下是一个完整的示例代码:

import 'package:flutter/material.dart';
import 'package:table_calendar/table_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: CalendarPage(),
    );
  }
}

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

class _CalendarPageState extends State<CalendarPage> with SingleTickerProviderStateMixin {
  CalendarController _controller;
  Map<DateTime, List<dynamic>> _events;

  @override
  void initState() {
    super.initState();

    _controller = CalendarController();

    // 初始化一些示例事件
    _events = {};

    // 添加一些示例事件到特定日期
    _addEvent(DateTime date, String title) {
      if (!_events.containsKey(date)) {
        _events[date] = [];
      }
      _events[date]!.add(title);
    }

    // 添加一些示例数据
    _addEvent(DateTime(2023, 10, 5), 'Event 1');
    _addEvent(DateTime(2023, 10, 15), 'Event 2');
    _addEvent(DateTime(2023, 10, 25), 'Event 3');
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Calendar Demo'),
      ),
      body: SingleChildScrollView(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            TableCalendar(
              _controller,
              events: _events,
              initialCalendarFormat: CalendarFormat.month,
              startingDayOfWeek: StartingDayOfWeek.monday,
              calendarStyle: CalendarStyle(
                todayColor: Colors.blue,
                selectedColor: Colors.deepOrange.withOpacity(0.3),
                todayStyle: TextStyle(fontWeight: FontWeight.bold),
                selectedTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
                daysOfWeekStyle: TextStyle(color: Colors.grey[800]),
              ),
              headerStyle: HeaderStyle(
                centerHeaderTitle: true,
                formatButtonTextStyle: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              builders: CalendarBuilders(
                selectedDayBuilder: (context, date, events) => Container(
                  margin: const EdgeInsets.all(4.0),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    color: Colors.deepOrange,
                    shape: BoxShape.circle,
                  ),
                  child: Text(
                    date.day.toString(),
                    style: TextStyle(color: Colors.white),
                  ),
                ),
                todayDayBuilder: (context, date, events) => Container(
                  margin: const EdgeInsets.all(4.0),
                  alignment: Alignment.center,
                  decoration: BoxDecoration(
                    color: Colors.blue.withOpacity(0.1),
                    shape: BoxShape.circle,
                  ),
                  child: Text(
                    date.day.toString(),
                    style: TextStyle(color: Colors.blue, fontWeight: FontWeight.bold),
                  ),
                ),
                markerBuilder: (context, date, events) => Badge(
                  badgeContent: Text(events.length.toString()),
                ),
              ),
              onDaySelected: (date, events) {
                setState(() {});
              },
              onVisibleDaysChanged: (days, month) {
                setState(() {});
              },
              onCalendarCreated: (CalendarController controller) {
                setState(() {});
              },
            ),
            // 显示选定日期的事件
            SizedBox(height: 10.0),
            Expanded(
              child: _buildEventList(),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildEventList() {
    return ListView.builder(
      shrinkWrap: true,
      itemCount: _controller.selectedEvents.length,
      itemBuilder: (context, index) {
        final event = _controller.selectedEvents[index];
        return Container(
          decoration: BoxDecoration(
            border: Border.all(color: Colors.grey),
            borderRadius: BorderRadius.circular(10),
          ),
          margin: EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
          child: ListTile(
            leading: Icon(Icons.event),
            title: Text(event.toString()),
          ),
        );
      },
    );
  }
}

class Badge extends StatelessWidget {
  final Widget badgeContent;

  const Badge({Key? key, required this.badgeContent}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Stack(
      alignment: Alignment.topRight,
      children: <Widget>[
        Positioned(
          right: -4,
          top: -4,
          child: Container(
            padding: EdgeInsets.all(2),
            decoration: BoxDecoration(
              color: Colors.redAccent,
              borderRadius: BorderRadius.circular(6),
            ),
            constraints: BoxConstraints(minWidth: 18, minHeight: 18),
            child: badgeContent,
          ),
        ),
      ],
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 初始化CalendarController:用于控制日历的显示和行为。
  2. 初始化事件数据_events是一个映射,将日期映射到事件列表。
  3. 构建日历:使用TableCalendar小部件,并配置样式和事件构建器。
  4. 处理选择事件:通过onDaySelected回调处理日期选择事件。
  5. 显示选定日期的事件:在日历下方显示选定日期的事件列表。

这个示例代码提供了一个基础的日历展示和处理事件的框架,你可以根据需要进一步自定义和扩展。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!