Flutter日历管理插件emor_calendar的使用

Flutter日历管理插件emor_calendar的使用

简介

此Flutter包提供了可自定义的日历,包含月视图和周视图,允许用户轻松导航和选择日期。该包还包括一个支持动态事件、日期范围限制和事件点颜色的事件日历小部件。

特性

  • 月视图日历:显示一整个月份,并可选择日期。当前日期会被高亮显示,星期天用红色标记。
  • 周视图日历:一次显示一周,并可通过滑动在不同周之间切换。
  • 事件列表:显示所选日期的事件列表,每个事件项都有边框和内边距以提高清晰度。

安装

将此包添加到你的项目中,通过在pubspec.yaml文件中包含以下内容:

dependencies:
  flutter:
    sdk: flutter
  emor_calendar: ^0.0.2

然后运行:

flutter pub get

使用

月视图日历

import 'package:emor_calendar/emorphis_month_calendar.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('月视图日历')),
        body: EmorphisMonthCalendar(),
      ),
    );
  }
}

周视图日历

import 'package:emor_calendar/emorphis_week_calendar.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('周视图日历')),
        body: EmorphisWeekCalendar(),
      ),
    );
  }
}

事件列表

事件列表会自动显示在你选择有事件的日期时。你可以通过修改emorphis_calendar.dart文件中的_buildEventList方法来自定义事件列表。

import 'package:emor_calendar/emorphis_week_calendar.dart';

class EventCalendarScreen extends StatefulWidget {
  @override
  _EventCalendarScreenState createState() => _EventCalendarScreenState();
}

class _EventCalendarScreenState extends State<EventCalendarScreen> {
  DateTime _focusedDay = DateTime.now();
  DateTime _selectedDay = DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day);
  Map<DateTime, List<String>> _events = {};

  @override
  Widget build(BuildContext context) {
    DateTime today = DateTime.now();
    DateTime minDate = DateTime(today.year - 1, today.month, today.day);
    DateTime maxDate = DateTime(today.year + 1, today.month, today.day);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Emorphis事件日历'),
        backgroundColor: Colors.blue.withOpacity(0.5),
        actions: [
          _buildAddEventButton(),
        ],
      ),
      body: Column(
        children: [
          EmorphisEventCalendar(
            focusedDay: _focusedDay,
            selectedDay: _selectedDay,
            events: _events,
            onDaySelected: (selectedDay) {
              setState(() {
                _selectedDay = selectedDay;
              });
            },
            onFocusedDayChanged: (focusedDay) {
              setState(() {
                _focusedDay = focusedDay;
              });
            },
            maxDate: maxDate,
            minDate: minDate,
          ),
          if (_events[_selectedDay] != null) _buildEventList(),
        ],
      ),
    );
  }

  Future<String?> _addEventDialog() {
    TextEditingController _controller = TextEditingController();

    return showDialog<String>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: const Text("添加事件"),
          content: TextField(
            controller: _controller,
            decoration: const InputDecoration(hintText: '输入事件详情'),
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text('取消'),
            ),
            TextButton(
              onPressed: () {
                Navigator.of(context).pop(_controller.text);
              },
              child: const Text('添加'),
            ),
          ],
        );
      },
    );
  }

  Widget _buildEventList() {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 10.0),
        child: ListView.builder(
          shrinkWrap: true,
          itemCount: _events[_selectedDay]?.length ?? 0,
          itemBuilder: (context, index) {
            return Container(
              padding: const EdgeInsets.all(10.0),
              margin: const EdgeInsets.only(bottom: 8.0),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.black, width: 0.5),
                borderRadius: BorderRadius.circular(8.0),
              ),
              child: Text(_events[_selectedDay]![index]),
            );
          },
        ),
      ),
    );
  }

  Widget _buildAddEventButton() {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ElevatedButton(
        onPressed: () async {
          String? event = await _addEventDialog();
          if (event != null && event.isNotEmpty) {
            final updatedEvents = Map<DateTime, List<String>>.from(_events);
            updatedEvents[_selectedDay] = updatedEvents[_selectedDay] ?? [];
            updatedEvents[_selectedDay]!.add(event);
            setState(() {
              _events = updatedEvents;
            });
          }
        },
        child: const Text("添加事件"),
      ),
    );
  }
}

节假日日历

import 'dart:convert';
import 'package:emor_calendar/calendar/emorphis_holiday_calendar.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'country.dart';

class HolidayCalendarScreen extends StatefulWidget {
  @override
  State<HolidayCalendarScreen> createState() => _HolidayCalendarScreenState();
}

class _HolidayCalendarScreenState extends State<HolidayCalendarScreen> {
  List<Holiday> holidays = [];
  DateTime _focusedDay = DateTime.now();
  String _selectedCountryCode = 'US'; // 默认国家代码

  final List<DropdownMenuItem<String>> dropdownItems =
      countryList.map((Country country) {
    return DropdownMenuItem<String>(
      value: country.code,
      child: Text(country.name),
    );
  }).toList();

  Future<List<Holiday>> fetchHolidays(String countryCode, int year) async {
    final response = await http.get(
      Uri.parse('https://date.nager.at/Api/v2/PublicHolidays/$year/$countryCode'),
    );
    if (response.statusCode == 200) {
      final List<dynamic> data = json.decode(response.body);
      return data.map((holiday) {
        return Holiday(
          DateTime.parse(holiday['date']),
          holiday['name'],
        );
      }).toList();
    } else {
      setState(() {
        _focusedDay = _focusedDay;
        holidays = [];
      });
      throw Exception('加载节假日失败');
    }
  }

  void _updateHolidays(DateTime newFocusedDay) {
    final newYear = newFocusedDay.year;
    fetchHolidays(_selectedCountryCode, newYear).then(
      (value) {
        holidays = [];
        setState(() {
          holidays = value;
          _focusedDay = newFocusedDay;
        });
      },
    );
  }

  void _onCountryCodeChanged(String? newCountryCode) {
    if (newCountryCode != null) {
      setState(() {
        _selectedCountryCode = newCountryCode;
        _updateHolidays(_focusedDay);
      });
    }
  }

  @override
  void initState() {
    super.initState();
    // 获取当前年份的节假日
    _updateHolidays(DateTime.now());
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('节假日日历'),
        actions: [
          Align(
            alignment: Alignment.centerLeft,
            child: SizedBox(
              width: 150, // 调整宽度
              child: DropdownButton<String>(
                value: _selectedCountryCode,
                onChanged: _onCountryCodeChanged,
                items: dropdownItems,
                isExpanded: true, // 确保下拉菜单填充宽度
                autofocus: true,
              ),
            ),
          ),
        ],
      ),
      body: EmorphisHolidayCalendar(
        holidays: holidays,
        initialFocusedDay: _focusedDay,
        initialSelectedDay: DateTime.now(),
        onFocusedDayChanged: _updateHolidays,
      ),
    );
  }
}

国家模型

class Country {
  final String code;
  final String name;

  Country(this.code, this.name);
}

final List<Country> countryList = [
  Country('AF', '阿富汗'),
  Country('AL', '阿尔巴尼亚'),
  Country('DZ', '阿尔及利亚'),
  Country('AD', '安道尔'),
  Country('AO', '安哥拉'),
  Country('AG', '安提瓜和巴布达'),
  Country('AR', '阿根廷'),
  Country('AM', '亚美尼亚'),
  Country('AU', '澳大利亚'),
  Country('AT', '奥地利'),
  Country('AZ', '阿塞拜疆'),
  Country('BS', '巴哈马'),
  Country('BH', '巴林'),
  Country('BD', '孟加拉国'),
  Country('BB', '巴巴多斯'),
  Country('BY', '白俄罗斯'),
  Country('BE', '比利时'),
  Country('BZ', '伯利兹'),
  Country('BJ', '贝宁'),
  Country('BT', '不丹'),
  Country('BO', '玻利维亚'),
  Country('BA', '波斯尼亚和黑塞哥维那'),
  Country('BW', '博茨瓦纳'),
  Country('BR', '巴西'),
  Country('BN', '文莱'),
  Country('BG', '保加利亚'),
  Country('BF', '布基纳法索'),
  Country('BI', '布隆迪'),
  Country('CV', '佛得角'),
  Country('KH', '柬埔寨'),
  Country('CM', '喀麦隆'),
  Country('CA', '加拿大'),
  Country('CF', '中非共和国'),
  Country('TD', '乍得'),
  Country('CL', '智利'),
  Country('CN', '中国'),
  Country('CO', '哥伦比亚'),
  Country('KM', '科摩罗'),
  Country('CG', '刚果(刚果-布拉柴维尔)'),
  Country('CR', '哥斯达黎加'),
  Country('HR', '克罗地亚'),
  Country('CU', '古巴'),
  Country('CY', '塞浦路斯'),
  Country('CZ', '捷克共和国'),
  Country('DK', '丹麦'),
  Country('DJ', '吉布提'),
  Country('DM', '多米尼克'),
  Country('DO', '多米尼加共和国'),
  Country('TL', '东帝汶'),
  Country('EC', '厄瓜多尔'),
  Country('EG', '埃及'),
  Country('SV', '萨尔瓦多'),
  Country('GQ', '赤道几内亚'),
  Country('ER', '厄立特里亚'),
  Country('EE', '爱沙尼亚'),
  Country('SZ', '斯威士兰'),
  Country('ET', '埃塞俄比亚'),
  Country('FJ', '斐济'),
  Country('FI', '芬兰'),
  Country('FR', '法国'),
  Country('GA', '加蓬'),
  Country('GM', '冈比亚'),
  Country('GE', '格鲁吉亚'),
  Country('DE', '德国'),
  Country('GH', '加纳'),
  Country('GR', '希腊'),
  Country('GD', '格林纳达'),
  Country('GT', '危地马拉'),
  Country('GN', '几内亚'),
  Country('GW', '几内亚比绍'),
  Country('GY', '圭亚那'),
  Country('HT', '海地'),
  Country('HN', '洪都拉斯'),
  Country('HU', '匈牙利'),
  Country('IS', '冰岛'),
  Country('IN', '印度'),
  Country('ID', '印度尼西亚'),
  Country('IR', '伊朗'),
  Country('IQ', '伊拉克'),
  Country('IE', '爱尔兰'),
  Country('IL', '以色列'),
  Country('IT', '意大利'),
  Country('JM', '牙买加'),
  Country('JP', '日本'),
  Country('JO', '约旦'),
  Country('KZ', '哈萨克斯坦'),
  Country('KE', '肯尼亚'),
  Country('KI', '基里巴斯'),
  Country('KP', '朝鲜'),
  Country('KR', '韩国'),
  Country('XK', '科索沃'),
  Country('KW', '科威特'),
  Country('KG', '吉尔吉斯斯坦'),
  Country('LA', '老挝'),
  Country('LV', '拉脱维亚'),
  Country('LB', '黎巴嫩'),
  Country('LS', '莱索托'),
  Country('LR', '利比里亚'),
  Country('LY', '利比亚'),
  Country('LI', '列支敦士登'),
  Country('LT', '立陶宛'),
  Country('LU', '卢森堡'),
  Country('MG', '马达加斯加'),
  Country('MW', '马拉维'),
  Country('MY', '马来西亚'),
  Country('MV', '马尔代夫'),
  Country('ML', '马里'),
  Country('MT', '马耳他'),
  Country('MH', '马绍尔群岛'),
  Country('MR', '毛里塔尼亚'),
  Country('MU', '毛里求斯'),
  Country('MX', '墨西哥'),
  Country('FM', '密克罗尼西亚联邦'),
  Country('MD', '摩尔多瓦'),
  Country('MC', '摩纳哥'),
  Country('MN', '蒙古'),
  Country('ME', '黑山'),
  Country('MA', '摩洛哥'),
  Country('MZ', '莫桑比克'),
  Country('MM', '缅甸'),
  Country('NA', '纳米比亚'),
  Country('NR', '瑙鲁'),
  Country('NP', '尼泊尔'),
  Country('NL', '荷兰'),
  Country('NZ', '新西兰'),
  Country('NI', '尼加拉瓜'),
  Country('NE', '尼日尔'),
  Country('NG', '尼日利亚'),
  Country('MK', '北马其顿'),
  Country('NO', '挪威'),
  Country('OM', '阿曼'),
  Country('PK', '巴基斯坦'),
  Country('PW', '帕劳'),
  Country('PA', '巴拿马'),
  Country('PG', '巴布亚新几内亚'),
  Country('PY', '巴拉圭'),
  Country('PE', '秘鲁'),
  Country('PH', '菲律宾'),
  Country('PL', '波兰'),
  Country('PT', '葡萄牙'),
  Country('QA', '卡塔尔'),
  Country('RO', '罗马尼亚'),
  Country('RU', '俄罗斯'),
  Country('RW', '卢旺达'),
  Country('KN', '圣基茨和尼维斯'),
  Country('LC', '圣卢西亚'),
  Country('VC', '圣文森特和格林纳丁斯'),
  Country('WS', '萨摩亚'),
  Country('SM', '圣马力诺'),
  Country('ST', '圣多美和普林西比'),
  Country('SA', '沙特阿拉伯'),
  Country('SN', '塞内加尔'),
  Country('RS', '塞尔维亚'),
  Country('SC', '塞舌尔'),
  Country('SL', '塞拉利昂'),
  Country('SG', '新加坡'),
  Country('SK', '斯洛伐克'),
  Country('SI', '斯洛文尼亚'),
  Country('SB', '所罗门群岛'),
  Country('SO', '索马里'),
  Country('ZA', '南非'),
  Country('SS', '南苏丹'),
  Country('ES', '西班牙'),
  Country('LK', '斯里兰卡'),
  Country('SD', '苏丹'),
  Country('SR', '苏里南'),
  Country('SE', '瑞典'),
  Country('CH', '瑞士'),
  Country('SY', '叙利亚'),
  Country('TW', '台湾'),
  Country('TJ', '塔吉克斯坦'),
  Country('TZ', '坦桑尼亚'),
  Country('TH', '泰国'),
  Country('TG', '多哥'),
  Country('TO', '汤加'),
  Country('TT', '特立尼达和多巴哥'),
  Country('TN', '突尼斯'),
  Country('TR', '土耳其'),
  Country('TM', '土库曼斯坦'),
  Country('TV', '图瓦卢'),
  Country('UG', '乌干达'),
  Country('UA', '乌克兰'),
  Country('AE', '阿拉伯联合酋长国'),
  Country('GB', '英国'),
  Country('US', '美国'),
  Country('UY', '乌拉圭'),
  Country('UZ', '乌兹别克斯坦'),
  Country('VU', '瓦努阿图'),
  Country('VA', '梵蒂冈城'),
  Country('VE', '委内瑞拉'),
  Country('VN', '越南'),
  Country('YE', '也门'),
  Country('ZM', '赞比亚'),
  Country('ZW', '津巴布韦'),
];

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

1 回复

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


emor_calendar 是一个用于 Flutter 的日历管理插件,它可以帮助你在应用中轻松地集成日历功能。以下是使用 emor_calendar 的基本步骤和示例代码。

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 emor_calendar 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  emor_calendar: ^1.0.0  # 请使用最新版本

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

2. 导入包

在你的 Dart 文件中导入 emor_calendar 包。

import 'package:emor_calendar/emor_calendar.dart';

3. 使用日历组件

emor_calendar 提供了 EmorCalendar 组件,你可以直接在应用中使用它。

import 'package:flutter/material.dart';
import 'package:emor_calendar/emor_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('Emor Calendar Example'),
        ),
        body: EmorCalendar(
          onDaySelected: (DateTime selectedDate) {
            print('Selected date: $selectedDate');
          },
        ),
      ),
    );
  }
}

4. 自定义日历

EmorCalendar 组件提供了多种自定义选项,例如设置初始日期、选择范围、自定义样式等。

EmorCalendar(
  initialDate: DateTime.now(),
  firstDate: DateTime(2020),
  lastDate: DateTime(2030),
  selectedDayColor: Colors.blue,
  todayColor: Colors.green,
  onDaySelected: (DateTime selectedDate) {
    print('Selected date: $selectedDate');
  },
);

5. 处理事件

你可以通过 onDaySelected 回调来处理用户选择的日期。

EmorCalendar(
  onDaySelected: (DateTime selectedDate) {
    // 在这里处理选择的日期
    print('Selected date: $selectedDate');
  },
);

6. 其他功能

emor_calendar 还支持其他功能,例如:

  • 多选日期:通过设置 selectedDatesonDatesSelected 回调来实现多选日期。
  • 自定义样式:通过 calendarStyle 参数来自定义日历的样式。
EmorCalendar(
  calendarStyle: CalendarStyle(
    selectedColor: Colors.blue,
    todayColor: Colors.green,
    weekendTextStyle: TextStyle(color: Colors.red),
  ),
);

7. 示例代码

以下是一个完整的示例代码,展示了如何使用 emor_calendar 插件。

import 'package:flutter/material.dart';
import 'package:emor_calendar/emor_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('Emor Calendar Example'),
        ),
        body: EmorCalendar(
          initialDate: DateTime.now(),
          firstDate: DateTime(2020),
          lastDate: DateTime(2030),
          selectedDayColor: Colors.blue,
          todayColor: Colors.green,
          onDaySelected: (DateTime selectedDate) {
            print('Selected date: $selectedDate');
          },
        ),
      ),
    );
  }
}
回到顶部