From 99283787b222cbfb12f2509f71e66d52e750bdc4 Mon Sep 17 00:00:00 2001
From: xiaodong <312569496@qq.com>
Date: Sun, 19 May 2019 00:32:13 +0800
Subject: [PATCH] publish pub
---
flutter_custom_calendar/.gitignore | 10 +
flutter_custom_calendar/.idea/encodings.xml | 4 +
.../.idea/libraries/Dart_Packages.xml | 172 ++
.../.idea/libraries/Dart_SDK.xml | 19 +
.../.idea/libraries/Flutter_Plugins.xml | 7 +
flutter_custom_calendar/.idea/misc.xml | 6 +
flutter_custom_calendar/.idea/modules.xml | 8 +
flutter_custom_calendar/.idea/workspace.xml | 295 +++
flutter_custom_calendar/.metadata | 10 +
flutter_custom_calendar/CHANGELOG.md | 11 +
flutter_custom_calendar/LICENSE | 25 +
flutter_custom_calendar/README.md | 245 ++
.../flutter_custom_calendar.iml | 19 +
.../lib/base_day_view.dart | 73 +
.../lib/base_week_bar.dart | 31 +
.../lib/calendar_view.dart | 82 +
.../lib/constants/constants.dart | 73 +
flutter_custom_calendar/lib/controller.dart | 317 +++
.../lib/default_combine_day_view.dart | 133 +
.../lib/default_custom_day_view.dart | 126 +
.../lib/default_week_bar.dart | 55 +
.../lib/demo_page/custom_style_page.dart | 172 ++
.../lib/demo_page/default_style_page.dart | 79 +
.../lib/demo_page/main.dart | 72 +
.../demo_page/multi_select_style_page.dart | 181 ++
.../lib/demo_page/progress_style_page.dart | 215 ++
.../lib/flutter_calendar.dart | 9 +
.../lib/flutter_custom_calendar.dart | 7 +
.../lib/model/date_model.dart | 62 +
flutter_custom_calendar/lib/month_view.dart | 164 ++
.../lib/month_view_pager.dart | 98 +
flutter_custom_calendar/lib/style/style.dart | 18 +
.../lib/utils/date_util.dart | 175 ++
.../lib/utils/lunar_util.dart | 1071 ++++++++
.../lib/utils/math_util.dart | 22 +
.../lib/utils/solar_term_util.dart | 2230 +++++++++++++++++
flutter_custom_calendar/lib/week_view.dart | 31 +
flutter_custom_calendar/pubspec.lock | 139 +
flutter_custom_calendar/pubspec.yaml | 53 +
.../test/flutter_custom_calendar_test.dart | 13 +
40 files changed, 6532 insertions(+)
create mode 100644 flutter_custom_calendar/.gitignore
create mode 100644 flutter_custom_calendar/.idea/encodings.xml
create mode 100644 flutter_custom_calendar/.idea/libraries/Dart_Packages.xml
create mode 100644 flutter_custom_calendar/.idea/libraries/Dart_SDK.xml
create mode 100644 flutter_custom_calendar/.idea/libraries/Flutter_Plugins.xml
create mode 100644 flutter_custom_calendar/.idea/misc.xml
create mode 100644 flutter_custom_calendar/.idea/modules.xml
create mode 100644 flutter_custom_calendar/.idea/workspace.xml
create mode 100644 flutter_custom_calendar/.metadata
create mode 100644 flutter_custom_calendar/CHANGELOG.md
create mode 100644 flutter_custom_calendar/LICENSE
create mode 100644 flutter_custom_calendar/README.md
create mode 100644 flutter_custom_calendar/flutter_custom_calendar.iml
create mode 100644 flutter_custom_calendar/lib/base_day_view.dart
create mode 100644 flutter_custom_calendar/lib/base_week_bar.dart
create mode 100644 flutter_custom_calendar/lib/calendar_view.dart
create mode 100644 flutter_custom_calendar/lib/constants/constants.dart
create mode 100644 flutter_custom_calendar/lib/controller.dart
create mode 100644 flutter_custom_calendar/lib/default_combine_day_view.dart
create mode 100644 flutter_custom_calendar/lib/default_custom_day_view.dart
create mode 100644 flutter_custom_calendar/lib/default_week_bar.dart
create mode 100644 flutter_custom_calendar/lib/demo_page/custom_style_page.dart
create mode 100644 flutter_custom_calendar/lib/demo_page/default_style_page.dart
create mode 100644 flutter_custom_calendar/lib/demo_page/main.dart
create mode 100644 flutter_custom_calendar/lib/demo_page/multi_select_style_page.dart
create mode 100644 flutter_custom_calendar/lib/demo_page/progress_style_page.dart
create mode 100644 flutter_custom_calendar/lib/flutter_calendar.dart
create mode 100644 flutter_custom_calendar/lib/flutter_custom_calendar.dart
create mode 100644 flutter_custom_calendar/lib/model/date_model.dart
create mode 100644 flutter_custom_calendar/lib/month_view.dart
create mode 100644 flutter_custom_calendar/lib/month_view_pager.dart
create mode 100644 flutter_custom_calendar/lib/style/style.dart
create mode 100644 flutter_custom_calendar/lib/utils/date_util.dart
create mode 100644 flutter_custom_calendar/lib/utils/lunar_util.dart
create mode 100644 flutter_custom_calendar/lib/utils/math_util.dart
create mode 100644 flutter_custom_calendar/lib/utils/solar_term_util.dart
create mode 100644 flutter_custom_calendar/lib/week_view.dart
create mode 100644 flutter_custom_calendar/pubspec.lock
create mode 100644 flutter_custom_calendar/pubspec.yaml
create mode 100644 flutter_custom_calendar/test/flutter_custom_calendar_test.dart
diff --git a/flutter_custom_calendar/.gitignore b/flutter_custom_calendar/.gitignore
new file mode 100644
index 0000000..446ed0d
--- /dev/null
+++ b/flutter_custom_calendar/.gitignore
@@ -0,0 +1,10 @@
+.DS_Store
+.dart_tool/
+
+.packages
+.pub/
+
+build/
+ios/.generated/
+ios/Flutter/Generated.xcconfig
+ios/Runner/GeneratedPluginRegistrant.*
diff --git a/flutter_custom_calendar/.idea/encodings.xml b/flutter_custom_calendar/.idea/encodings.xml
new file mode 100644
index 0000000..15a15b2
--- /dev/null
+++ b/flutter_custom_calendar/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.idea/libraries/Dart_Packages.xml b/flutter_custom_calendar/.idea/libraries/Dart_Packages.xml
new file mode 100644
index 0000000..b06b342
--- /dev/null
+++ b/flutter_custom_calendar/.idea/libraries/Dart_Packages.xml
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.idea/libraries/Dart_SDK.xml b/flutter_custom_calendar/.idea/libraries/Dart_SDK.xml
new file mode 100644
index 0000000..79108aa
--- /dev/null
+++ b/flutter_custom_calendar/.idea/libraries/Dart_SDK.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.idea/libraries/Flutter_Plugins.xml b/flutter_custom_calendar/.idea/libraries/Flutter_Plugins.xml
new file mode 100644
index 0000000..b0f6971
--- /dev/null
+++ b/flutter_custom_calendar/.idea/libraries/Flutter_Plugins.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.idea/misc.xml b/flutter_custom_calendar/.idea/misc.xml
new file mode 100644
index 0000000..5c94cb2
--- /dev/null
+++ b/flutter_custom_calendar/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.idea/modules.xml b/flutter_custom_calendar/.idea/modules.xml
new file mode 100644
index 0000000..5f98220
--- /dev/null
+++ b/flutter_custom_calendar/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/flutter_custom_calendar/.idea/workspace.xml b/flutter_custom_calendar/.idea/workspace.xml
new file mode 100644
index 0000000..90afe1e
--- /dev/null
+++ b/flutter_custom_calendar/.idea/workspace.xml
@@ -0,0 +1,295 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ flutter_calendar
+
+
+ flutter_custom_calendar
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1558196651106
+
+
+ 1558196651106
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/.metadata b/flutter_custom_calendar/.metadata
new file mode 100644
index 0000000..d770b6d
--- /dev/null
+++ b/flutter_custom_calendar/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+ revision: d42db56b52657d7557664393ac1fe9a734a6b6e7
+ channel: master
+
+project_type: package
diff --git a/flutter_custom_calendar/CHANGELOG.md b/flutter_custom_calendar/CHANGELOG.md
new file mode 100644
index 0000000..1d28c96
--- /dev/null
+++ b/flutter_custom_calendar/CHANGELOG.md
@@ -0,0 +1,11 @@
+## [0.0.1] - 2019/5/19.
+
+## 主要功能
+* 支持公历,农历,节气,传统节日,常用节假日
+* 日期范围设置,默认支持的最大日期范围为1971.01-2055.12
+* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
+* 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。
+* 跳转到指定日期,默认支持动画切换
+* 自定义日历Item,支持组合widget的方式和利用canvas绘制的方式
+* 自定义顶部的WeekBar
+* 可以给Item添加自定义的额外数据,实现各种额外的功能。比如实现进度条风格的日历
\ No newline at end of file
diff --git a/flutter_custom_calendar/LICENSE b/flutter_custom_calendar/LICENSE
new file mode 100644
index 0000000..7670ad0
--- /dev/null
+++ b/flutter_custom_calendar/LICENSE
@@ -0,0 +1,25 @@
+BSD 2-Clause License
+
+Copyright (c) 2019, LXD312569496
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/flutter_custom_calendar/README.md b/flutter_custom_calendar/README.md
new file mode 100644
index 0000000..b028a2c
--- /dev/null
+++ b/flutter_custom_calendar/README.md
@@ -0,0 +1,245 @@
+FlutterCalendarWidget
+
+Flutter上的一个日历控件,可以定制成自己想要的样子。
+
+
+
+
+
+
+## 主要功能
+* 支持公历,农历,节气,传统节日,常用节假日
+* 日期范围设置,默认支持的最大日期范围为1971.01-2055.12
+* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
+* 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。
+* 跳转到指定日期,默认支持动画切换
+* 自定义日历Item,支持组合widget的方式和利用canvas绘制的方式
+* 自定义顶部的WeekBar
+* 可以给Item添加自定义的额外数据,实现各种额外的功能。比如实现进度条风格的日历
+
+## 使用
+引入flutter_custom_calendar,就可以使用CalendarViewWidget,配置CalendarController就可以了。
+```
+CalendarViewWidget({@required this.calendarController, this.boxDecoration});
+```
+* boxDecoration用来配置整体的背景
+* 利用CalendarController来配置一些数据,并且可以通过CalendarController进行一些操作或者事件监听,比如滚动到下一个月,获取当前被选中的Item等等。
+
+下面是CalendarController中一些支持自定义配置的属性。不配置的话,会有对应的默认值。
+```
+//默认是单选,可以配置为MODE_SINGLE_SELECT,MODE_MULTI_SELECT
+int selectMode;
+
+//日历显示的最小年份和最大年份
+int minYear;
+int maxYear;
+
+//日历显示的最小年份的月份,最大年份的月份
+int minYearMonth;
+int maxYearMonth;
+
+//日历显示的当前的年份和月份
+int nowYear;
+int nowMonth;
+
+//可操作的范围设置,比如点击选择
+int minSelectYear;
+int minSelectMonth;
+int minSelectDay;
+
+int maxSelectYear;
+int maxSelectMonth;
+int maxSelectDay; //注意:不能超过对应月份的总天数
+
+Set selectedDateList = new Set(); //被选中的日期,用于多选
+DateModel selectDateModel; //当前选择项,用于单选
+int maxMultiSelectCount; //多选,最多选多少个
+Map extraDataMap = new Map(); //自定义额外的数据
+
+//各种事件回调
+OnMonthChange monthChange; //月份切换事件
+OnCalendarSelect calendarSelect; //点击选择事件
+OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围
+OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数
+
+//支持自定义绘制
+DayWidgetBuilder dayWidgetBuilder; //创建日历item
+WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar
+```
+
+### 利用controller添加监听事件
+比如月份切换事件、点击选择事件。
+```
+//月份切换监听
+void addMonthChangeListener(OnMonthChange listener) {
+ this.monthChange = listener;
+}
+//点击选择监听
+void addOnCalendarSelectListener(OnCalendarSelect listener) {
+ this.calendarSelect = listener;
+}
+//多选超出指定范围
+void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) {
+ this.multiSelectOutOfRange = listener;
+}
+//多选超出限制个数
+void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) {
+ this.multiSelectOutOfSize = listener;
+}
+```
+
+### 利用controller来控制日历的切换,支持配置动画
+
+```
+//跳转到指定日期
+void moveToCalendar(int year, int month, int day,
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease});
+//切换到下一年
+void moveToNextYear();
+//切换到上一年
+void moveToPreviousYear();
+//切换到下一个月份,
+void moveToNextMonth();
+//切换到上一个月份
+void moveToPreviousMonth();
+```
+
+### 利用controller来获取日历的一些数据信息
+```
+// 获取当前的月份
+DateTime getCurrentMonth();
+//获取被选中的日期,多选
+Set getMultiSelectCalendar();
+//获取被选中的日期,单选
+DateModel getSingleSelectCalendar();
+```
+
+### 自定义UI
+
+包括自定义WeekBar、自定义日历Item,默认使用的都是DefaultXXXWidget。
+
+只要继承对应的Base类,实现相应的方法,然后只需要在配置Controller的时候,实现相应的Builder方法就可以了。
+```
+//支持自定义绘制
+DayWidgetBuilder dayWidgetBuilder; //创建日历item
+WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar
+```
+### 自定义WeekBar
+继承BaseWeekBar,重写getWeekBarItem(index)方法就可以。随便你怎么实现,只需要返回一个Widget就可以了。
+```
+class DefaultWeekBar extends BaseWeekBar {
+ const DefaultWeekBar({Key key}) : super(key: key);
+ @override
+ Widget getWeekBarItem(int index) {
+ /**
+ * 自定义Widget
+ */
+ return new Container(
+ height: 40,
+ alignment: Alignment.center,
+ child: new Text(
+ Constants.WEEK_LIST[index],
+ style: topWeekTextStyle,
+ ),
+ );
+ }
+}
+```
+### 自定义日历Item:
+提供两种方法,一种是利用组合widget的方式来创建,一种是利用Canvas来自定义绘制Item。最后只需要在CalendarController的构造参数中进行配置就可以了。
+* 继承BaseCombineDayWidget,重写getNormalWidget(DateModel dateModel)
+和getSelectedWidget(DateModel dateModel)就可以了,返回对应的widget就行。
+```
+class DefaultCombineDayWidget extends BaseCombineDayWidget {
+ DefaultCombineDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ Widget getNormalWidget(DateModel dateModel) {
+ //实现默认状态下的UI
+ }
+
+ @override
+ Widget getSelectedWidget(DateModel dateModel) {
+ //绘制被选中的UI
+ }
+}
+```
+* 继承BaseCustomDayWidget,重写drawNormal和drawSelected的两个方法就可以了,利用canvas自己绘制Item。
+```
+class DefaultCustomDayWidget extends BaseCustomDayWidget {
+ DefaultCustomDayWidget(DateModel dateModel) : super(dateModel);
+ @override
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ //实现默认状态下的UI
+ defaultDrawNormal(dateModel, canvas, size);
+ }
+ @override
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ //绘制被选中的UI
+ defaultDrawSelected(dateModel, canvas, size);
+ }
+}
+```
+### DateModel实体类
+日历所用的日期的实体类DateModel,有下面这些属性。
+```
+/**
+ * 日期的实体类
+ */
+class DateModel {
+ int year;
+ int month;
+ int day = 1;
+ int lunarYear;
+ int lunarMonth;
+ int lunarDay;
+ String lunarString; //农历字符串
+ String solarTerm; //24节气
+ String gregorianFestival; //公历节日
+ String traditionFestival; //传统农历节日
+ bool isCurrentDay; //是否是今天
+ bool isLeapYear; //是否是闰年
+ bool isWeekend; //是否是周末
+ int leapMonth; //是否是闰月
+ Object extraData; //自定义的额外数据
+ bool isInRange = false; //是否在范围内,比如可以实现在某个范围外,设置置灰的功能
+ bool isSelected; //是否被选中,用来实现一些标记或者选择功能
+ @override
+ String toString() {
+ return 'DateModel{year: $year, month: $month, day: $day}';
+ } //如果是闰月,则返回闰月
+
+ //转化成DateTime格式
+ DateTime getDateTime() {
+ return new DateTime(year, month, day);
+ }
+ //根据DateTime创建对应的model,并初始化农历和传统节日等信息
+ static DateModel fromDateTime(DateTime dateTime) {
+ DateModel dateModel = new DateModel()
+ ..year = dateTime.year
+ ..month = dateTime.month
+ ..day = dateTime.day;
+ LunarUtil.setupLunarCalendar(dateModel);
+ return dateModel;
+ }
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is DateModel &&
+ runtimeType == other.runtimeType &&
+ year == other.year &&
+ month == other.month &&
+ day == other.day;
+ @override
+ int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
+}
+```
+
+## TODO LIST
+* 优化代码实现
+* 支持屏蔽指定的某些天
+* 继续写几个不同风格的Demo
+* 支持周视图
+* 支持动画切换周视图和月视图
diff --git a/flutter_custom_calendar/flutter_custom_calendar.iml b/flutter_custom_calendar/flutter_custom_calendar.iml
new file mode 100644
index 0000000..8d48a06
--- /dev/null
+++ b/flutter_custom_calendar/flutter_custom_calendar.iml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/flutter_custom_calendar/lib/base_day_view.dart b/flutter_custom_calendar/lib/base_day_view.dart
new file mode 100644
index 0000000..a1894cb
--- /dev/null
+++ b/flutter_custom_calendar/lib/base_day_view.dart
@@ -0,0 +1,73 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+
+/**
+ * 通过canvas自定义item,只需实现相关的方法就可以
+ */
+abstract class BaseCustomDayWidget extends StatelessWidget {
+ DateModel dateModel;
+
+ BaseCustomDayWidget(
+ this.dateModel,
+ );
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ child: new CustomPaint(
+ painter:
+ //根据isSelected标志获取对应的item
+ dateModel.isSelected
+ ? new CustomDayWidgetPainter(dateModel,
+ drawDayWidget: drawSelected)
+ : new CustomDayWidgetPainter(dateModel,
+ drawDayWidget: drawNormal),
+ ),
+ );
+ }
+
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size);
+
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size);
+}
+
+class CustomDayWidgetPainter extends CustomPainter {
+ DateModel dateModel;
+
+ DrawDayWidget drawDayWidget; //普通样式是必须的
+
+ CustomDayWidgetPainter(this.dateModel, {this.drawDayWidget});
+
+ Paint textPaint;
+
+ @override
+ void paint(Canvas canvas, Size size) {
+ drawDayWidget(dateModel, canvas, size);
+ }
+
+ @override
+ bool shouldRepaint(CustomPainter oldDelegate) {
+ return true;
+ }
+}
+
+/**
+ * 通过组合widget创建item,只需实现相关的方法就可以
+ */
+abstract class BaseCombineDayWidget extends StatelessWidget {
+ DateModel dateModel;
+
+ BaseCombineDayWidget(this.dateModel);
+
+ @override
+ Widget build(BuildContext context) {
+ return dateModel.isSelected
+ ? getSelectedWidget(dateModel)
+ : getNormalWidget(dateModel);
+ }
+
+ Widget getNormalWidget(DateModel dateModel);
+
+ Widget getSelectedWidget(DateModel dateModel);
+}
diff --git a/flutter_custom_calendar/lib/base_week_bar.dart b/flutter_custom_calendar/lib/base_week_bar.dart
new file mode 100644
index 0000000..b9fcf20
--- /dev/null
+++ b/flutter_custom_calendar/lib/base_week_bar.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+
+/**
+ * 顶部的固定的周显示
+ */
+abstract class BaseWeekBar extends StatelessWidget {
+ const BaseWeekBar({Key key}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ child: new Row(
+ children: getWeekDayWidget(),
+ ),
+ );
+ }
+
+ Widget getWeekBarItem(int index);
+
+ List getWeekDayWidget() {
+ return List.generate(7, (index) {
+ return getChild(index);
+ });
+ }
+
+ Widget getChild(int index) {
+ return new Expanded(
+ child: getWeekBarItem(index),
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/calendar_view.dart b/flutter_custom_calendar/lib/calendar_view.dart
new file mode 100644
index 0000000..87ae2f4
--- /dev/null
+++ b/flutter_custom_calendar/lib/calendar_view.dart
@@ -0,0 +1,82 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/constants/constants.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/month_view_pager.dart';
+
+import 'controller.dart';
+
+/**
+ * 暂时默认是周一开始的
+ */
+class CalendarViewWidget extends StatefulWidget {
+ //整体的背景设置
+ BoxDecoration boxDecoration;
+
+ //控制器
+ CalendarController calendarController;
+
+ CalendarViewWidget({@required this.calendarController, this.boxDecoration});
+
+ @override
+ _CalendarViewWidgetState createState() => _CalendarViewWidgetState();
+}
+
+class _CalendarViewWidgetState extends State {
+ double itemHeight;
+ double totalHeight;
+
+ @override
+ void initState() {}
+
+ @override
+ Widget build(BuildContext context) {
+ //暂时先这样写死,提前计算布局的高度,不然会出现问题:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand.
+ itemHeight = MediaQuery.of(context).size.width / 7;
+ totalHeight = itemHeight * 6 + 10 * (6 - 1);
+ return Container(
+ //外部可以自定义背景设置
+ decoration: widget.boxDecoration,
+ child: new Column(
+ children: [
+ /**
+ * 利用const,避免每次setState都会刷新到这顶部的view
+ */
+ widget.calendarController.weekBarItemWidgetBuilder(),
+ Container(
+ height: totalHeight,
+ child: MonthViewPager(
+ selectMode: widget.calendarController.selectMode,
+ monthChange: (int year, int month) {
+ widget.calendarController.monthChange(year, month);
+ },
+ calendarSelect: (dateModel) {
+ widget.calendarController.selectDateModel =dateModel;
+ widget.calendarController.calendarSelect(dateModel);
+ },
+ monthList: widget.calendarController.monthList,
+ pageController: widget.calendarController.pageController,
+ selectedDateList: widget.calendarController.selectedDateList,
+ selectDateModel: widget.calendarController.selectDateModel,
+ dayWidgetBuilder: widget.calendarController.dayWidgetBuilder,
+ minSelectDate: DateModel()
+ ..year = widget.calendarController.minSelectYear
+ ..month = widget.calendarController.minSelectMonth
+ ..day = widget.calendarController.minSelectDay,
+ maxSelectDate: DateModel()
+ ..year = widget.calendarController.maxSelectYear
+ ..month = widget.calendarController.maxSelectMonth
+ ..day = widget.calendarController.maxSelectDay,
+ maxMultiSelectCount:
+ widget.calendarController.maxMultiSelectCount,
+ multiSelectOutOfRange:
+ widget.calendarController.multiSelectOutOfRange,
+ multiSelectOutOfSize:
+ widget.calendarController.multiSelectOutOfSize,
+ extraDataMap: widget.calendarController.extraDataMap,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/constants/constants.dart b/flutter_custom_calendar/lib/constants/constants.dart
new file mode 100644
index 0000000..62d6e67
--- /dev/null
+++ b/flutter_custom_calendar/lib/constants/constants.dart
@@ -0,0 +1,73 @@
+class Constants {
+
+ //单选或者多选模式
+ static const int MODE_SINGLE_SELECT = 1;
+ static const int MODE_MULTI_SELECT = 2;
+
+ /**
+ * 一周七天
+ */
+ static const List WEEK_LIST = [
+ "周一",
+ "周二",
+ "周三",
+ "周四",
+ "周五",
+ "周六",
+ "周日"
+ ];
+
+ /**
+ * 农历的月份
+ */
+ static const List LUNAR_MONTH_TEXT = [
+ "春节",
+ "二月",
+ "三月",
+ "四月",
+ "五月",
+ "六月",
+ "七月",
+ "八月",
+ "九月",
+ "十月",
+ "冬月",
+ "腊月",
+ ];
+
+ /**
+ * 农历的日期
+ */
+ static const List LUNAR_DAY_TEXT = [
+ "初一",
+ "初二",
+ "初三",
+ "初四",
+ "初五",
+ "初六",
+ "初七",
+ "初八",
+ "初九",
+ "初十",
+ "十一",
+ "十二",
+ "十三",
+ "十四",
+ "十五",
+ "十六",
+ "十七",
+ "十八",
+ "十九",
+ "二十",
+ "廿一",
+ "廿二",
+ "廿三",
+ "廿四",
+ "廿五",
+ "廿六",
+ "廿七",
+ "廿八",
+ "廿九",
+ "三十"
+ ];
+}
diff --git a/flutter_custom_calendar/lib/controller.dart b/flutter_custom_calendar/lib/controller.dart
new file mode 100644
index 0000000..c18c37a
--- /dev/null
+++ b/flutter_custom_calendar/lib/controller.dart
@@ -0,0 +1,317 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/default_combine_day_view.dart';
+import 'package:flutter_custom_calendar/default_custom_day_view.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/default_week_bar.dart';
+import 'package:flutter_custom_calendar/constants/constants.dart';
+
+/**
+ * 利用controller来控制视图
+ */
+
+class CalendarController {
+ static const Set EMPTY_SET = {};
+ static const Map EMPTY_MAP = {};
+
+ //默认是单选,可以配置为MODE_SINGLE_SELECT,MODE_MULTI_SELECT
+ int selectMode;
+
+ //日历显示的最小年份和最大年份
+ int minYear;
+ int maxYear;
+
+ //日历显示的最小年份的月份,最大年份的月份
+ int minYearMonth;
+ int maxYearMonth;
+
+ //日历显示的当前的年份和月份
+ int nowYear;
+ int nowMonth;
+
+ //可操作的范围设置,比如点击选择
+ int minSelectYear;
+ int minSelectMonth;
+ int minSelectDay;
+
+ int maxSelectYear;
+ int maxSelectMonth;
+ int maxSelectDay; //注意:不能超过对应月份的总天数
+
+ Set selectedDateList = new Set(); //被选中的日期,用于多选
+ DateModel selectDateModel; //当前选择项,用于单选
+ int maxMultiSelectCount; //多选,最多选多少个
+ Map extraDataMap = new Map(); //自定义额外的数据
+
+ //各种事件回调
+ OnMonthChange monthChange; //月份切换事件
+ OnCalendarSelect calendarSelect; //点击选择事件
+ OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围
+ OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数
+
+ //支持自定义绘制
+ DayWidgetBuilder dayWidgetBuilder; //创建日历item
+ WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar
+
+ /**
+ * 下面的信息不是配置的
+ */
+ List monthList = new List(); //月份list
+ PageController pageController;
+
+ CalendarController(
+ {int selectMode = Constants.MODE_SINGLE_SELECT,
+ DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget,
+ WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget,
+ int minYear = 1971,
+ int maxYear = 2055,
+ int minYearMonth = 1,
+ int maxYearMonth = 12,
+ int nowYear = -1,
+ int nowMonth = -1,
+ int minSelectYear = 1971,
+ int minSelectMonth = 1,
+ int minSelectDay = 1,
+ int maxSelectYear = 2055,
+ int maxSelectMonth = 12,
+ int maxSelectDay = 30,
+ Set selectedDateTimeList = EMPTY_SET,
+ DateModel selectDateModel,
+ int maxMultiSelectCount = 9999,
+ Map extraDataMap = EMPTY_MAP}) {
+ this.selectMode = selectMode;
+ this.minYear = minYear;
+ this.maxYear = maxYear;
+ this.minYearMonth = minYearMonth;
+ this.maxYearMonth = maxYearMonth;
+ this.nowYear = nowYear;
+ this.nowMonth = nowMonth;
+ this.minSelectYear = minSelectYear;
+ this.minSelectMonth = minSelectMonth;
+ this.minSelectDay = minSelectDay;
+ this.maxSelectYear = maxSelectYear;
+ this.maxSelectMonth = maxSelectMonth;
+ this.maxSelectDay = maxSelectDay;
+ this.selectDateModel = selectDateModel;
+ this.dayWidgetBuilder = dayWidgetBuilder;
+ this.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder;
+ this.maxMultiSelectCount = maxMultiSelectCount;
+ this.extraDataMap = extraDataMap;
+
+ this.selectedDateList = Set();
+ if (selectedDateTimeList != null && selectedDateTimeList.isNotEmpty) {
+ this.selectedDateList.addAll(selectedDateTimeList.map((dateTime) {
+ return DateModel.fromDateTime(dateTime);
+ }).toSet());
+ }
+
+ //初始化pageController,initialPage默认是当前时间对于的页面
+ int initialPage;
+ int nowMonthIndex = 0;
+ monthList.clear();
+ for (int i = minYear; i <= maxYear; i++) {
+ for (int j = 1; j <= 12; j++) {
+ if (i == minYear && j < minYearMonth) {
+ continue;
+ }
+ if (i == maxYear && j > maxYearMonth) {
+ continue;
+ }
+ DateModel dateModel = new DateModel();
+ dateModel.year = i;
+ dateModel.month = j;
+
+ //如果没有配置当前时间,设置成当前的时间
+ if (nowYear == -1 || nowMonth == -1) {
+ nowYear = DateTime.now().year;
+ nowMonth = DateTime.now().month;
+ }
+ if (i == nowYear && j == nowMonth) {
+ initialPage = nowMonthIndex;
+ }
+ monthList.add(dateModel);
+ nowMonthIndex++;
+ }
+ }
+ this.pageController = new PageController(initialPage: initialPage);
+ }
+
+ //月份切换监听
+ void addMonthChangeListener(OnMonthChange listener) {
+ this.monthChange = listener;
+ }
+
+ //点击选择监听
+ void addOnCalendarSelectListener(OnCalendarSelect listener) {
+ this.calendarSelect = listener;
+ }
+
+ //多选超出指定范围
+ void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) {
+ this.multiSelectOutOfRange = listener;
+ }
+
+ //多选超出限制个数
+ void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) {
+ this.multiSelectOutOfSize = listener;
+ }
+
+ //跳转到指定日期
+ void moveToCalendar(int year, int month, int day,
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease}) {
+ DateModel dateModel = DateModel.fromDateTime(DateTime(year, month, day));
+ //计算目标索引
+ int targetPage = monthList.indexOf(dateModel);
+ if (targetPage == -1) {
+ return;
+ }
+ if (needAnimation) {
+ pageController.animateToPage(targetPage,
+ duration: duration, curve: curve);
+ } else {
+ pageController.jumpToPage(targetPage);
+ }
+ }
+
+ //切换到下一年
+ void moveToNextYear(
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease}) {
+ DateTime targetDateTime =
+ monthList[pageController.page.toInt() + 12].getDateTime();
+ moveToCalendar(
+ targetDateTime.year, targetDateTime.month, targetDateTime.day,
+ needAnimation: needAnimation, duration: duration, curve: curve);
+ }
+
+ //切换到上一年
+ void moveToPreviousYear(
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease}) {
+ DateTime targetDateTime =
+ monthList[pageController.page.toInt() - 12].getDateTime();
+ moveToCalendar(
+ targetDateTime.year, targetDateTime.month, targetDateTime.day,
+ needAnimation: needAnimation, duration: duration, curve: curve);
+ }
+
+ //切换到下一个月份,
+ void moveToNextMonth(
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease}) {
+ DateTime targetDateTime =
+ monthList[pageController.page.toInt() + 1].getDateTime();
+ moveToCalendar(
+ targetDateTime.year, targetDateTime.month, targetDateTime.day,
+ needAnimation: needAnimation, duration: duration, curve: curve);
+ }
+
+ //切换到上一个月份
+ void moveToPreviousMonth(
+ {bool needAnimation = false,
+ Duration duration = const Duration(milliseconds: 500),
+ Curve curve = Curves.ease}) {
+ DateTime targetDateTime =
+ monthList[pageController.page.toInt() - 1].getDateTime();
+ moveToCalendar(
+ targetDateTime.year, targetDateTime.month, targetDateTime.day,
+ needAnimation: needAnimation, duration: duration, curve: curve);
+ }
+
+ // 获取当前的月份
+ DateModel getCurrentMonth() {
+ return monthList[pageController.page.toInt()];
+ }
+
+ //获取被选中的日期,多选
+ Set getMultiSelectCalendar() {
+ if (selectedDateList.isEmpty) {
+ return null;
+ }
+ return selectedDateList;
+ }
+
+ //获取被选中的日期,单选
+ DateModel getSingleSelectCalendar() {
+ if (selectDateModel == null) {
+ return null;
+ }
+ return selectDateModel;
+ }
+}
+
+/**
+ * 默认的weekBar
+ */
+Widget defaultWeekBarWidget() {
+ return DefaultWeekBar();
+}
+
+/**
+ * 使用canvas绘制item
+ */
+Widget defaultCustomDayWidget(DateModel dateModel) {
+ return DefaultCustomDayWidget(
+ dateModel,
+ );
+}
+
+/**
+ * 使用组合widget的方式构造item
+ */
+Widget defaultCombineDayWidget(DateModel dateModel) {
+ return new DefaultCombineDayWidget(
+ dateModel,
+ );
+}
+
+/**
+ * 判断是否在范围内,不在范围内的话,可以置灰
+ */
+bool defaultInRange(DateModel dateModel) {
+ return true;
+}
+
+/**
+ * 月份切换事件
+ */
+typedef void OnMonthChange(int year, int month);
+
+/**
+ * 日期选择事件
+ */
+typedef void OnCalendarSelect(DateModel dateModel);
+
+/**
+ * 多选超出指定范围
+ */
+typedef void OnMultiSelectOutOfRange();
+
+/**
+ * 多选超出限制个数
+ */
+typedef void OnMultiSelectOutOfSize();
+
+/**
+ * 可以创建自定义样式的item
+ */
+typedef Widget DayWidgetBuilder(DateModel dateModel);
+
+/**
+ * 是否可以点击,外部来进行判断,默认都可以点击
+ */
+typedef bool CanClick(DateModel dateModel);
+
+/**
+ * 可以自定义绘制每个Item,这种扩展性好一点,以后可以提供给外部进行自定义绘制
+ */
+typedef void DrawDayWidget(DateModel dateModel, Canvas canvas, Size size);
+
+/**
+ * 自定义顶部weekBar
+ */
+typedef Widget WeekBarItemWidgetBuilder();
diff --git a/flutter_custom_calendar/lib/default_combine_day_view.dart b/flutter_custom_calendar/lib/default_combine_day_view.dart
new file mode 100644
index 0000000..f1c19b7
--- /dev/null
+++ b/flutter_custom_calendar/lib/default_combine_day_view.dart
@@ -0,0 +1,133 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_day_view.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/style/style.dart';
+
+/**
+ * 默认的利用组合widget的方式构造item
+ */
+//class DefaultCombineDayWidget extends StatelessWidget {
+// DateModel dateModel;
+//
+// DefaultCombineDayWidget(this.dateModel);
+//
+// @override
+// Widget build(BuildContext context) {
+// return Container(
+// margin: EdgeInsets.only(top: 5, bottom: 5),
+// decoration: dateModel.isSelected
+// ? new BoxDecoration(color: Colors.red, shape: BoxShape.circle)
+// : null,
+// child: new Stack(
+// alignment: Alignment.center,
+// children: [
+// new Column(
+// mainAxisSize: MainAxisSize.max,
+// crossAxisAlignment: CrossAxisAlignment.center,
+// children: [
+// //公历
+// new Expanded(
+// child: Center(
+// child: new Text(
+// dateModel.day.toString(),
+// style: currentMonthTextStyle,
+// ),
+// ),
+// ),
+//
+// //农历
+// new Expanded(
+// child: Center(
+// child: new Text(
+// "${dateModel.lunarString}",
+// style: lunarTextStyle,
+// ),
+// ),
+// ),
+// ],
+// )
+// ],
+// ),
+// );
+// }
+//}
+
+class DefaultCombineDayWidget extends BaseCombineDayWidget {
+ DefaultCombineDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ Widget getNormalWidget(DateModel dateModel) {
+ return Container(
+ margin: EdgeInsets.all(8),
+ child: new Stack(
+ alignment: Alignment.center,
+ children: [
+ new Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ //公历
+ new Expanded(
+ child: Center(
+ child: new Text(
+ dateModel.day.toString(),
+ style: currentMonthTextStyle,
+ ),
+ ),
+ ),
+
+ //农历
+ new Expanded(
+ child: Center(
+ child: new Text(
+ "${dateModel.lunarString}",
+ style: lunarTextStyle,
+ ),
+ ),
+ ),
+ ],
+ )
+ ],
+ ),
+ );
+ }
+
+ @override
+ Widget getSelectedWidget(DateModel dateModel) {
+ return Container(
+ margin: EdgeInsets.all(8),
+ foregroundDecoration:
+ new BoxDecoration(border: Border.all(width: 2, color: Colors.blue)),
+ child: new Stack(
+ alignment: Alignment.center,
+ children: [
+ new Column(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ //公历
+ new Expanded(
+ child: Center(
+ child: new Text(
+ dateModel.day.toString(),
+ style: currentMonthTextStyle,
+ ),
+ ),
+ ),
+
+ //农历
+ new Expanded(
+ child: Center(
+ child: new Text(
+ "${dateModel.lunarString}",
+ style: lunarTextStyle,
+ ),
+ ),
+ ),
+ ],
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/default_custom_day_view.dart b/flutter_custom_calendar/lib/default_custom_day_view.dart
new file mode 100644
index 0000000..43a553b
--- /dev/null
+++ b/flutter_custom_calendar/lib/default_custom_day_view.dart
@@ -0,0 +1,126 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_day_view.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/style/style.dart';
+
+/**
+ * 这里定义成一个StatelessWidget,状态是外部的父控件传进来参数控制就行,自己不弄state类
+ */
+
+class DefaultCustomDayWidget extends BaseCustomDayWidget {
+ DefaultCustomDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ defaultDrawNormal(dateModel, canvas, size);
+ }
+
+ @override
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ defaultDrawSelected(dateModel, canvas, size);
+ }
+}
+
+//class DefaultCustomDayWidget extends StatelessWidget {
+// DateModel dateModel;
+//
+// DefaultCustomDayWidget(this.dateModel);
+//
+// @override
+// Widget build(BuildContext context) {
+// return Container(
+// child: new CustomPaint(
+// painter: CustomDayWidgetPainter(
+// dateModel,
+// ),
+// ),
+// );
+// }
+//}
+//
+//class CustomDayWidgetPainter extends CustomPainter {
+// DateModel dateModel;
+//
+// drawNormal normalDraw; //普通样式是必须的
+// drawSelected selectedDraw;
+//
+// CustomDayWidgetPainter(this.dateModel,
+// {this.normalDraw = defaultDrawNormal,
+// this.selectedDraw = defaultDrawSelected});
+//
+// Paint textPaint;
+//
+// @override
+// void paint(Canvas canvas, Size size) {
+//// print("paint:$size");
+// if (dateModel.isSelected) {
+// selectedDraw(dateModel, canvas, size);
+// } else {
+// normalDraw(dateModel, canvas, size);
+// }
+// }
+//
+// @override
+// bool shouldRepaint(CustomPainter oldDelegate) {
+// return true;
+// }
+//}
+
+/**
+ * 默认的样式
+ */
+void defaultDrawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text =
+ TextSpan(text: dateModel.day.toString(), style: currentMonthTextStyle)
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(text: dateModel.lunarString, style: lunarTextStyle)
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+}
+
+/**
+ * 被选中的样式
+ */
+void defaultDrawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ //绘制背景
+ Paint backGroundPaint = new Paint()
+ ..color = Colors.blue
+ ..style = PaintingStyle.stroke
+ ..strokeWidth = 2;
+ double padding = 8;
+ canvas.drawRect(
+ Rect.fromPoints(Offset(padding, padding),
+ Offset(size.width - padding, size.height - padding)),
+ backGroundPaint);
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text =
+ TextSpan(text: dateModel.day.toString(), style: currentMonthTextStyle)
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(text: dateModel.lunarString, style: lunarTextStyle)
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+}
diff --git a/flutter_custom_calendar/lib/default_week_bar.dart b/flutter_custom_calendar/lib/default_week_bar.dart
new file mode 100644
index 0000000..6c34ee8
--- /dev/null
+++ b/flutter_custom_calendar/lib/default_week_bar.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_week_bar.dart';
+import 'package:flutter_custom_calendar/style/style.dart';
+import 'constants/constants.dart';
+
+///**
+// * 顶部的固定的周显示
+// */
+//class DefaultWeekBar extends StatelessWidget {
+// const DefaultWeekBar({Key key}) : super(key: key);
+//
+// @override
+// Widget build(BuildContext context) {
+// return Container(
+// child: new Row(
+// children: getWeekDayWidget(),
+// ),
+// );
+// }
+//}
+//
+//List getWeekDayWidget() {
+// return List.generate(7, (index) {
+// return getChild(Constants.WEEK_LIST[index]);
+// });
+//}
+//
+//Widget getChild(String title) {
+// return new Expanded(
+// child: new Container(
+// color: RandomColor.next(),
+// height: 40,
+// alignment: Alignment.center,
+// child: new Text(
+// title,
+// style: topWeekTextStyle,
+// ),
+// ));
+//}
+
+class DefaultWeekBar extends BaseWeekBar {
+ const DefaultWeekBar({Key key}) : super(key: key);
+
+ @override
+ Widget getWeekBarItem(int index) {
+ return new Container(
+ height: 40,
+ alignment: Alignment.center,
+ child: new Text(
+ Constants.WEEK_LIST[index],
+ style: topWeekTextStyle,
+ ),
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/demo_page/custom_style_page.dart b/flutter_custom_calendar/lib/demo_page/custom_style_page.dart
new file mode 100644
index 0000000..c53ecfb
--- /dev/null
+++ b/flutter_custom_calendar/lib/demo_page/custom_style_page.dart
@@ -0,0 +1,172 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_day_view.dart';
+import 'package:flutter_custom_calendar/base_week_bar.dart';
+import 'package:flutter_custom_calendar/calendar_view.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+
+class CustomStylePage extends StatefulWidget {
+ CustomStylePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _CustomStylePageState createState() => _CustomStylePageState();
+}
+
+class _CustomStylePageState extends State {
+ String text;
+
+ CalendarController controller;
+
+ @override
+ void initState() {
+ text = "${DateTime.now().year}年${DateTime.now().month}月";
+
+ controller = new CalendarController(weekBarItemWidgetBuilder: () {
+ return CustomStyleWeekBarItem();
+ }, dayWidgetBuilder: (dateModel) {
+ return CustomStyleDayWidget(dateModel);
+ });
+
+ controller.addMonthChangeListener(
+ (year, month) {
+ setState(() {
+ text = "$year年$month月";
+ });
+ },
+ );
+
+ controller.addOnCalendarSelectListener((dateModel) {
+ //刷新选择的时间
+ setState(() {});
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: new Container(
+ child: new Column(
+ children: [
+ new Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ new IconButton(
+ icon: Icon(Icons.navigate_before),
+ onPressed: () {
+ controller.moveToPreviousMonth();
+ }),
+ new Text(text),
+ new IconButton(
+ icon: Icon(Icons.navigate_next),
+ onPressed: () {
+ controller.moveToNextMonth();
+ }),
+ ],
+ ),
+ CalendarViewWidget(
+ calendarController: controller,
+ ),
+ new Text(
+ "自定义创建Item\n选中的时间:\n${controller.getSingleSelectCalendar().toString()}"),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {},
+ tooltip: 'Increment',
+ child: Icon(Icons.add),
+ ), // This trailing comma makes auto-formatting nicer for build methods.
+ );
+ }
+}
+
+class CustomStyleWeekBarItem extends BaseWeekBar {
+ List weekList = ["一", "二", "三", "四", "五", "六", "日"];
+
+ @override
+ Widget getWeekBarItem(int index) {
+ return new Container(
+ child: new Center(
+ child: new Text(weekList[index]),
+ ),
+ );
+ }
+}
+
+class CustomStyleDayWidget extends BaseCustomDayWidget {
+ CustomStyleDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ bool isWeekend = dateModel.isWeekend;
+ bool isInRange = dateModel.isInRange;
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(
+ color: !isInRange
+ ? Colors.grey
+ : isWeekend ? Colors.blue : Colors.black,
+ fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(
+ color: !isInRange
+ ? Colors.grey
+ : isWeekend ? Colors.blue : Colors.grey,
+ fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+
+ @override
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ //绘制背景
+ Paint backGroundPaint = new Paint()
+ ..color = Colors.blue
+ ..strokeWidth = 2;
+ double padding = 8;
+ canvas.drawCircle(Offset(size.width / 2, size.height / 2),
+ (size.width - padding) / 2, backGroundPaint);
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(color: Colors.white, fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(color: Colors.white, fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+}
diff --git a/flutter_custom_calendar/lib/demo_page/default_style_page.dart b/flutter_custom_calendar/lib/demo_page/default_style_page.dart
new file mode 100644
index 0000000..3e4bc7c
--- /dev/null
+++ b/flutter_custom_calendar/lib/demo_page/default_style_page.dart
@@ -0,0 +1,79 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/calendar_view.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+
+class DefaultStylePage extends StatefulWidget {
+ DefaultStylePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _DefaultStylePageState createState() => _DefaultStylePageState();
+}
+
+class _DefaultStylePageState extends State {
+ String text;
+
+ CalendarController controller;
+
+ @override
+ void initState() {
+ text = "${DateTime.now().year}年${DateTime.now().month}月";
+
+ controller = new CalendarController();
+
+ controller.addMonthChangeListener(
+ (year, month) {
+ setState(() {
+ text = "$year年$month月";
+ });
+ },
+ );
+
+ controller.addOnCalendarSelectListener((dateModel) {
+ //刷新选择的时间
+ setState(() {});
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: new Container(
+ child: new Column(
+ children: [
+ new Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ new IconButton(
+ icon: Icon(Icons.navigate_before),
+ onPressed: () {
+ controller.moveToPreviousMonth();
+ }),
+ new Text(text),
+ new IconButton(
+ icon: Icon(Icons.navigate_next),
+ onPressed: () {
+ controller.moveToNextMonth();
+ }),
+ ],
+ ),
+ CalendarViewWidget(
+ calendarController: controller,
+ ),
+ new Text(
+ "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar().toString()}"),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {},
+ tooltip: 'Increment',
+ child: Icon(Icons.add),
+ ), // This trailing comma makes auto-formatting nicer for build methods.
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/demo_page/main.dart b/flutter_custom_calendar/lib/demo_page/main.dart
new file mode 100644
index 0000000..76ed0b7
--- /dev/null
+++ b/flutter_custom_calendar/lib/demo_page/main.dart
@@ -0,0 +1,72 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/demo_page/custom_style_page.dart';
+import 'package:flutter_custom_calendar/demo_page/default_style_page.dart';
+import 'package:flutter_custom_calendar/demo_page/multi_select_style_page.dart';
+import 'package:flutter_custom_calendar/demo_page/progress_style_page.dart';
+
+void main() => runApp(MyApp());
+
+class MyApp extends StatelessWidget {
+ // This widget is the root of your application.
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ routes: {
+ "/default": (context) => DefaultStylePage(
+ title: "默认风格+单选",
+ ),
+ "/custom": (context) => CustomStylePage(
+ title: "自定义风格+单选",
+ ),
+ "/multi_select": (context) => MultiSelectStylePage(
+ title: "自定义风格+多选",
+ ),
+ "/progress": (context) => ProgressStylePage(
+ title: "进度条风格+单选",
+ ),
+ },
+ title: 'Flutter Demo',
+ theme: ThemeData(
+ primarySwatch: Colors.blue,
+ ),
+ home: HomePage());
+ }
+}
+
+class HomePage extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Scaffold(
+ body: SafeArea(
+ child: new Column(
+ children: [
+ new RaisedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, "/default");
+ },
+ child: new Text("默认风格+单选"),
+ ),
+ new RaisedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, "/custom");
+ },
+ child: new Text("自定义风格+单选"),
+ ),
+ new RaisedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, "/multi_select");
+ },
+ child: new Text("自定义风格+多选"),
+ ),
+ new RaisedButton(
+ onPressed: () {
+ Navigator.pushNamed(context, "/progress");
+ },
+ child: new Text("进度条风格+单选"),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/flutter_custom_calendar/lib/demo_page/multi_select_style_page.dart b/flutter_custom_calendar/lib/demo_page/multi_select_style_page.dart
new file mode 100644
index 0000000..4454092
--- /dev/null
+++ b/flutter_custom_calendar/lib/demo_page/multi_select_style_page.dart
@@ -0,0 +1,181 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_day_view.dart';
+import 'package:flutter_custom_calendar/base_week_bar.dart';
+import 'package:flutter_custom_calendar/calendar_view.dart';
+import 'package:flutter_custom_calendar/constants/constants.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+
+class MultiSelectStylePage extends StatefulWidget {
+ MultiSelectStylePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _MultiSelectStylePageState createState() => _MultiSelectStylePageState();
+}
+
+class _MultiSelectStylePageState extends State {
+ String text;
+
+ CalendarController controller;
+
+ @override
+ void initState() {
+ text = "${DateTime.now().year}年${DateTime.now().month}月";
+
+ controller = new CalendarController(
+ selectMode: Constants.MODE_MULTI_SELECT,
+ maxMultiSelectCount: 5,
+ minSelectYear: 2019,
+ minSelectMonth: 5,
+ minSelectDay: 20,
+ weekBarItemWidgetBuilder: () {
+ return CustomStyleWeekBarItem();
+ },
+ dayWidgetBuilder: (dateModel) {
+ return CustomStyleDayWidget(dateModel);
+ });
+
+ controller.addMonthChangeListener(
+ (year, month) {
+ setState(() {
+ text = "$year年$month月";
+ });
+ },
+ );
+
+ controller.addOnCalendarSelectListener((dateModel) {
+ //刷新选择的时间
+ setState(() {});
+ });
+
+ controller.addOnMultiSelectOutOfSizeListener((){
+ print("超出限制个数");
+ });
+ controller.addOnMultiSelectOutOfRangeListener((){
+ print("超出范围限制");
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: new Container(
+ child: new Column(
+ children: [
+ new Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ new IconButton(
+ icon: Icon(Icons.navigate_before),
+ onPressed: () {
+ controller.moveToPreviousMonth();
+ }),
+ new Text(text),
+ new IconButton(
+ icon: Icon(Icons.navigate_next),
+ onPressed: () {
+ controller.moveToNextMonth();
+ }),
+ ],
+ ),
+ CalendarViewWidget(
+ calendarController: controller,
+ ),
+ new Text(
+ "多选模式\n选中的时间:\n${controller.getMultiSelectCalendar().toString()}"),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {},
+ tooltip: 'Increment',
+ child: Icon(Icons.add),
+ ), // This trailing comma makes auto-formatting nicer for build methods.
+ );
+ }
+}
+
+class CustomStyleWeekBarItem extends BaseWeekBar {
+ List weekList = ["一", "二", "三", "四", "五", "六", "日"];
+
+ @override
+ Widget getWeekBarItem(int index) {
+ return new Container(
+ child: new Center(
+ child: new Text(weekList[index]),
+ ),
+ );
+ }
+}
+
+class CustomStyleDayWidget extends BaseCustomDayWidget {
+ CustomStyleDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ bool isWeekend = dateModel.isWeekend;
+ bool isInRange = dateModel.isInRange;
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(
+ color: !isInRange ? Colors.grey : Colors.black, fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(
+ color: !isInRange ? Colors.grey : Colors.grey, fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+
+ @override
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ //绘制背景
+ Paint backGroundPaint = new Paint()
+ ..color = Colors.blue
+ ..strokeWidth = 2;
+ double padding = 8;
+ canvas.drawCircle(Offset(size.width / 2, size.height / 2),
+ (size.width - padding) / 2, backGroundPaint);
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(color: Colors.white, fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(color: Colors.white, fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+}
diff --git a/flutter_custom_calendar/lib/demo_page/progress_style_page.dart b/flutter_custom_calendar/lib/demo_page/progress_style_page.dart
new file mode 100644
index 0000000..31e8d96
--- /dev/null
+++ b/flutter_custom_calendar/lib/demo_page/progress_style_page.dart
@@ -0,0 +1,215 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/base_day_view.dart';
+import 'package:flutter_custom_calendar/base_week_bar.dart';
+import 'package:flutter_custom_calendar/calendar_view.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'dart:math';
+
+class ProgressStylePage extends StatefulWidget {
+ ProgressStylePage({Key key, this.title}) : super(key: key);
+
+ final String title;
+
+ @override
+ _ProgressStylePageState createState() => _ProgressStylePageState();
+}
+
+class _ProgressStylePageState extends State {
+ String text;
+
+ CalendarController controller;
+
+ @override
+ void initState() {
+ text = "${DateTime.now().year}年${DateTime.now().month}月";
+
+ DateTime now = DateTime.now();
+ DateTime temp = DateTime(now.year, now.month, now.day);
+
+ Map progressMap = {
+ temp.add(Duration(days: 1)): 0,
+ temp.add(Duration(days: 2)): 20,
+ temp.add(Duration(days: 3)): 40,
+ temp.add(Duration(days: 4)): 60,
+ temp.add(Duration(days: 5)): 80,
+ temp.add(Duration(days: 6)): 100,
+ };
+
+ controller = new CalendarController(
+ extraDataMap: progressMap,
+ weekBarItemWidgetBuilder: () {
+ return CustomStyleWeekBarItem();
+ },
+ dayWidgetBuilder: (dateModel) {
+ return ProgressStyleDayWidget(dateModel);
+ });
+
+ controller.addMonthChangeListener(
+ (year, month) {
+ setState(() {
+ text = "$year年$month月";
+ });
+ },
+ );
+
+ controller.addOnCalendarSelectListener((dateModel) {
+ //刷新选择的时间
+ setState(() {});
+ });
+
+ controller.addOnMultiSelectOutOfSizeListener(() {
+ print("超出限制个数");
+ });
+ controller.addOnMultiSelectOutOfRangeListener(() {
+ print("超出范围限制");
+ });
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: Text(widget.title),
+ ),
+ body: new Container(
+ child: new Column(
+ children: [
+ new Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ new IconButton(
+ icon: Icon(Icons.navigate_before),
+ onPressed: () {
+ controller.moveToPreviousMonth();
+ }),
+ new Text(text),
+ new IconButton(
+ icon: Icon(Icons.navigate_next),
+ onPressed: () {
+ controller.moveToNextMonth();
+ }),
+ ],
+ ),
+ CalendarViewWidget(
+ calendarController: controller,
+ ),
+ new Text(
+ "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar().toString()}"),
+ ],
+ ),
+ ),
+ floatingActionButton: FloatingActionButton(
+ onPressed: () {},
+ tooltip: 'Increment',
+ child: Icon(Icons.add),
+ ), // This trailing comma makes auto-formatting nicer for build methods.
+ );
+ }
+}
+
+class CustomStyleWeekBarItem extends BaseWeekBar {
+ List weekList = ["一", "二", "三", "四", "五", "六", "日"];
+
+ @override
+ Widget getWeekBarItem(int index) {
+ return new Container(
+ child: new Center(
+ child: new Text(weekList[index]),
+ ),
+ );
+ }
+}
+
+class ProgressStyleDayWidget extends BaseCustomDayWidget {
+ ProgressStyleDayWidget(DateModel dateModel) : super(dateModel);
+
+ @override
+ void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
+ bool isInRange = dateModel.isInRange;
+
+ //进度条
+ int progress = dateModel.extraData;
+ if (progress != null && progress != 0) {
+ double padding = 8;
+ Paint paint = Paint()
+ ..color = Colors.grey
+ ..style = PaintingStyle.stroke
+ ..strokeWidth = 2;
+
+ canvas.drawCircle(Offset(size.width / 2, size.height / 2),
+ (size.width - padding) / 2, paint);
+
+ paint.color = Colors.blue;
+
+ double startAngle = -90 * pi / 180;
+ double sweepAngle = pi / 180 * (360 * progress / 100);
+
+ canvas.drawArc(
+ Rect.fromCircle(
+ center: Offset(size.width / 2, size.height / 2),
+ radius: (size.width - padding) / 2),
+ startAngle,
+ sweepAngle,
+ false,
+ paint);
+ }
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(
+ color: !isInRange ? Colors.grey : Colors.black, fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(
+ color: !isInRange ? Colors.grey : Colors.grey, fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+
+ @override
+ void drawSelected(DateModel dateModel, Canvas canvas, Size size) {
+ //绘制背景
+ Paint backGroundPaint = new Paint()
+ ..color = Colors.blue
+ ..strokeWidth = 2;
+ double padding = 8;
+ canvas.drawCircle(Offset(size.width / 2, size.height / 2),
+ (size.width - padding) / 2, backGroundPaint);
+
+ //顶部的文字
+ TextPainter dayTextPainter = new TextPainter()
+ ..text = TextSpan(
+ text: dateModel.day.toString(),
+ style: new TextStyle(color: Colors.white, fontSize: 16))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ dayTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ dayTextPainter.paint(canvas, Offset(0, 10));
+
+ //下面的文字
+ TextPainter lunarTextPainter = new TextPainter()
+ ..text = new TextSpan(
+ text: dateModel.lunarString,
+ style: new TextStyle(color: Colors.white, fontSize: 12))
+ ..textDirection = TextDirection.ltr
+ ..textAlign = TextAlign.center;
+
+ lunarTextPainter.layout(minWidth: size.width, maxWidth: size.width);
+ lunarTextPainter.paint(canvas, Offset(0, size.height / 2));
+ }
+}
diff --git a/flutter_custom_calendar/lib/flutter_calendar.dart b/flutter_custom_calendar/lib/flutter_calendar.dart
new file mode 100644
index 0000000..285c92b
--- /dev/null
+++ b/flutter_custom_calendar/lib/flutter_calendar.dart
@@ -0,0 +1,9 @@
+export 'package:flutter_custom_calendar/controller.dart';
+export 'package:flutter_custom_calendar/calendar_view.dart';
+export 'package:flutter_custom_calendar/base_day_view.dart';
+export 'package:flutter_custom_calendar/base_week_bar.dart';
+export 'package:flutter_custom_calendar/constants/constants.dart';
+export 'package:flutter_custom_calendar/model/date_model.dart';
+export 'package:flutter_custom_calendar/default_combine_day_view.dart';
+export 'package:flutter_custom_calendar/default_custom_day_view.dart';
+export 'package:flutter_custom_calendar/default_week_bar.dart';
diff --git a/flutter_custom_calendar/lib/flutter_custom_calendar.dart b/flutter_custom_calendar/lib/flutter_custom_calendar.dart
new file mode 100644
index 0000000..8d25904
--- /dev/null
+++ b/flutter_custom_calendar/lib/flutter_custom_calendar.dart
@@ -0,0 +1,7 @@
+library flutter_custom_calendar;
+
+/// A Calculator.
+class Calculator {
+ /// Returns [value] plus 1.
+ int addOne(int value) => value + 1;
+}
diff --git a/flutter_custom_calendar/lib/model/date_model.dart b/flutter_custom_calendar/lib/model/date_model.dart
new file mode 100644
index 0000000..b6d6328
--- /dev/null
+++ b/flutter_custom_calendar/lib/model/date_model.dart
@@ -0,0 +1,62 @@
+import 'package:flutter_custom_calendar/utils/lunar_util.dart';
+
+/**
+ * 日期的实体类
+ */
+class DateModel {
+ int year;
+ int month;
+ int day = 1;
+
+ int lunarYear;
+ int lunarMonth;
+ int lunarDay;
+
+ String lunarString; //农历字符串
+ String solarTerm; //24节气
+ String gregorianFestival; //公历节日
+ String traditionFestival; //传统农历节日
+
+ bool isCurrentDay; //是否是今天
+ bool isLeapYear; //是否是闰年
+ bool isWeekend; //是否是周末
+ int leapMonth; //是否是闰月
+
+ Object extraData; //自定义的额外数据
+
+ bool isInRange = false; //是否在范围内,比如可以实现在某个范围外,设置置灰的功能
+ bool isSelected; //是否被选中,用来实现一些标记或者选择功能
+ bool isCanClick = true; //todo:是否可点击:设置范围外的日历不可点击,或者可以通过自定义拦截点击事件来设置true或者false
+
+ @override
+ String toString() {
+ return 'DateModel{year: $year, month: $month, day: $day}';
+ } //如果是闰月,则返回闰月
+
+ //转化成DateTime格式
+ DateTime getDateTime() {
+ return new DateTime(year, month, day);
+ }
+
+ //根据DateTime创建对应的model,并初始化农历和传统节日等信息
+ static DateModel fromDateTime(DateTime dateTime) {
+ DateModel dateModel = new DateModel()
+ ..year = dateTime.year
+ ..month = dateTime.month
+ ..day = dateTime.day;
+ LunarUtil.setupLunarCalendar(dateModel);
+ return dateModel;
+ }
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is DateModel &&
+ runtimeType == other.runtimeType &&
+ year == other.year &&
+ month == other.month &&
+ day == other.day;
+
+ @override
+ int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode;
+}
diff --git a/flutter_custom_calendar/lib/month_view.dart b/flutter_custom_calendar/lib/month_view.dart
new file mode 100644
index 0000000..76f015d
--- /dev/null
+++ b/flutter_custom_calendar/lib/month_view.dart
@@ -0,0 +1,164 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/constants/constants.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/default_custom_day_view.dart';
+import 'package:flutter_custom_calendar/default_combine_day_view.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/utils/date_util.dart';
+
+/**
+ * 月视图,显示整个月的日子
+ */
+class MonthView extends StatefulWidget {
+ OnCalendarSelect onCalendarSelectListener;
+
+ Set selectedDateList; //被选中的日期
+
+ DateModel selectDateModel; //当前选择项,用于单选
+
+ DayWidgetBuilder dayWidgetBuilder;
+
+ OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围
+ OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数
+
+ int year;
+ int month;
+ int day;
+
+ DateModel minSelectDate;
+ DateModel maxSelectDate;
+
+ int selectMode;
+ int maxMultiSelectCount;
+
+ Map extraDataMap; //自定义额外的数据
+
+ MonthView(
+ {@required this.year,
+ @required this.month,
+ this.day,
+ this.onCalendarSelectListener,
+ this.dayWidgetBuilder,
+ this.selectedDateList,
+ this.selectDateModel,
+ this.minSelectDate,
+ this.maxSelectDate,
+ this.selectMode,
+ this.multiSelectOutOfSize,
+ this.multiSelectOutOfRange,
+ this.maxMultiSelectCount,
+ this.extraDataMap});
+
+ @override
+ _MonthViewState createState() => _MonthViewState();
+}
+
+class _MonthViewState extends State {
+ List items;
+
+ int lineCount;
+
+ double itemHeight;
+ double totalHeight;
+ double mainSpacing = 10;
+
+ int year;
+ int month;
+
+ DateModel selectDateModel; //当前选择项,用于单选
+
+ @override
+ void initState() {
+ super.initState();
+
+ year = widget.year;
+ month = widget.month;
+
+ items = DateUtil.initCalendarForMonthView(
+ year, month, DateTime.now(), DateTime.sunday,
+ minSelectDate: widget.minSelectDate,
+ maxSelectDate: widget.maxSelectDate,
+ extraDataMap: widget.extraDataMap);
+
+ lineCount = DateUtil.getMonthViewLineCount(year, month);
+
+ selectDateModel = widget.selectDateModel;
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ itemHeight = MediaQuery.of(context).size.width / 7;
+ totalHeight = itemHeight * lineCount + mainSpacing * (lineCount - 1);
+
+ return GestureDetector(
+ onVerticalDragStart: (DragStartDetails detail) {
+ print("onHorizontalDragStart:$detail");
+ },
+ child: Container(height: totalHeight, child: getView()));
+ }
+
+ Widget getView() {
+ return new GridView.builder(
+ physics: NeverScrollableScrollPhysics(),
+ gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
+ crossAxisCount: 7, mainAxisSpacing: 10),
+ itemCount: 7 * lineCount,
+ itemBuilder: (context, index) {
+ DateModel dateModel = items[index];
+ //判断是否被选择
+ if (widget.selectMode == Constants.MODE_MULTI_SELECT) {
+ if (widget.selectedDateList.contains(dateModel)) {
+ dateModel.isSelected = true;
+ } else {
+ dateModel.isSelected = false;
+ }
+ } else {
+ if (selectDateModel == dateModel) {
+ dateModel.isSelected = true;
+ } else {
+ dateModel.isSelected = false;
+ }
+ }
+
+ return GestureDetector(
+ onTap: () {
+ //范围外不可点击
+ if (!dateModel.isInRange) {
+ //多选回调
+ if (widget.selectMode == Constants.MODE_MULTI_SELECT) {
+ widget.multiSelectOutOfRange();
+ }
+ return;
+ }
+
+ if (widget.selectMode == Constants.MODE_MULTI_SELECT) {
+ //多选,判断是否超过限制,超过范围
+ if (widget.selectedDateList.length ==
+ widget.maxMultiSelectCount) {
+ widget.multiSelectOutOfSize();
+ return;
+ }
+
+ //多选也可以弄这些单选的代码
+ selectDateModel = dateModel;
+ widget.selectDateModel = dateModel;
+ widget.onCalendarSelectListener(dateModel);
+ setState(() {
+ if (widget.selectedDateList.contains(dateModel)) {
+ widget.selectedDateList.remove(dateModel);
+ } else {
+ widget.selectedDateList.add(dateModel);
+ }
+ });
+ } else {
+ selectDateModel = dateModel;
+ widget.selectDateModel = dateModel;
+ widget.onCalendarSelectListener(dateModel);
+ setState(() {});
+ }
+ },
+ child: widget.dayWidgetBuilder(dateModel),
+ );
+ });
+ }
+}
diff --git a/flutter_custom_calendar/lib/month_view_pager.dart b/flutter_custom_calendar/lib/month_view_pager.dart
new file mode 100644
index 0000000..75bea5d
--- /dev/null
+++ b/flutter_custom_calendar/lib/month_view_pager.dart
@@ -0,0 +1,98 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/controller.dart';
+import 'package:flutter_custom_calendar/default_custom_day_view.dart';
+import 'package:flutter_custom_calendar/default_combine_day_view.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/month_view.dart';
+
+class MonthViewPager extends StatefulWidget {
+ final OnMonthChange monthChange;
+ final OnCalendarSelect calendarSelect;
+ final DayWidgetBuilder dayWidgetBuilder;
+ OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围
+ OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数
+
+ Set selectedDateList; //被选中的日期,用于多选
+ DateModel selectDateModel; //当前选择项,用于单选
+
+ final List monthList;
+ PageController pageController;
+
+ DateModel minSelectDate;
+ DateModel maxSelectDate;
+
+ int selectMode;
+ int maxMultiSelectCount;
+
+ Map extraDataMap ; //自定义额外的数据
+
+ MonthViewPager(
+ {this.monthChange,
+ this.calendarSelect,
+ this.monthList,
+ this.pageController,
+ this.selectedDateList,
+ this.selectDateModel,
+ this.dayWidgetBuilder,
+ this.minSelectDate,
+ this.maxSelectDate,
+ this.selectMode,
+ this.maxMultiSelectCount,
+ this.multiSelectOutOfRange,
+ this.multiSelectOutOfSize,
+ this.extraDataMap});
+
+ @override
+ _MonthViewPagerState createState() => _MonthViewPagerState();
+}
+
+class _MonthViewPagerState extends State {
+ @override
+ void initState() {}
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ child: PageView.builder(
+ onPageChanged: (position) {
+ //月份的变化
+ DateModel dateModel = widget.monthList[position];
+ widget.monthChange(dateModel.year, dateModel.month);
+ },
+ controller: widget.pageController,
+ itemBuilder: (context, index) {
+ DateModel dateModel = widget.monthList[index];
+ return new MonthView(
+ selectMode: widget.selectMode,
+ year: dateModel.year,
+ month: dateModel.month,
+ selectDateModel: widget.selectDateModel,
+ selectedDateList: widget.selectedDateList,
+ onCalendarSelectListener: widget.calendarSelect,
+ dayWidgetBuilder: widget.dayWidgetBuilder,
+ minSelectDate: widget.minSelectDate,
+ maxSelectDate: widget.maxSelectDate,
+ maxMultiSelectCount: widget.maxMultiSelectCount,
+ multiSelectOutOfRange: widget.multiSelectOutOfRange,
+ multiSelectOutOfSize: widget.multiSelectOutOfSize,
+ extraDataMap: widget.extraDataMap,
+ );
+ },
+ itemCount: widget.monthList.length,
+ ),
+ );
+
+// return SliverFillViewport(
+// delegate: SliverChildBuilderDelegate((context, index) {
+// DateModel dateModel = widget.monthList[index];
+// return new MonthView(
+// year: dateModel.year,
+// month: dateModel.month,
+// selectDateModel: widget.selectDateModel,
+// selectedDateList: widget.selectedDateList,
+// onCalendarSelectListener: widget.calendarSelect,
+// );
+// }, childCount: widget.monthList.length),
+// );
+ }
+}
diff --git a/flutter_custom_calendar/lib/style/style.dart b/flutter_custom_calendar/lib/style/style.dart
new file mode 100644
index 0000000..09faae3
--- /dev/null
+++ b/flutter_custom_calendar/lib/style/style.dart
@@ -0,0 +1,18 @@
+
+import 'package:flutter/material.dart';
+
+
+//顶部7天的文案
+TextStyle topWeekTextStyle=new TextStyle(fontSize: 12);
+
+//当前月份的日期的文字
+TextStyle currentMonthTextStyle =
+new TextStyle(color: Colors.black, fontSize: 16);
+
+//下一个月或者上一个月的日期的文字
+TextStyle preOrNextMonthTextStyle =
+new TextStyle(color: Colors.grey, fontSize: 18);
+
+//农历的字体
+TextStyle lunarTextStyle = new TextStyle(color: Colors.grey, fontSize: 12);
+
diff --git a/flutter_custom_calendar/lib/utils/date_util.dart b/flutter_custom_calendar/lib/utils/date_util.dart
new file mode 100644
index 0000000..c139d24
--- /dev/null
+++ b/flutter_custom_calendar/lib/utils/date_util.dart
@@ -0,0 +1,175 @@
+import 'dart:math';
+
+import 'package:flutter_custom_calendar/model/date_model.dart';
+
+/**
+ * 工具类
+ */
+class DateUtil {
+ /**
+ * 判断一个日期是否是周末,即周六日
+ */
+ static bool isWeekend(DateTime dateTime) {
+ return dateTime.weekday == DateTime.saturday ||
+ dateTime.weekday == DateTime.sunday;
+ }
+
+ /**
+ * 获取某月的天数
+ *
+ * @param year 年
+ * @param month 月
+ * @return 某月的天数
+ */
+ static int getMonthDaysCount(int year, int month) {
+ int count = 0;
+ //判断大月份
+ if (month == 1 ||
+ month == 3 ||
+ month == 5 ||
+ month == 7 ||
+ month == 8 ||
+ month == 10 ||
+ month == 12) {
+ count = 31;
+ }
+
+ //判断小月
+ if (month == 4 || month == 6 || month == 9 || month == 11) {
+ count = 30;
+ }
+
+ //判断平年与闰年
+ if (month == 2) {
+ if (isLeapYear(year)) {
+ count = 29;
+ } else {
+ count = 28;
+ }
+ }
+ return count;
+ }
+
+ /**
+ * 是否是今天
+ */
+ static bool isCurrentDay(int year, int month, int day) {
+ return new DateTime(year, month, day).difference(DateTime.now()).inDays ==
+ 0;
+ }
+
+ /**
+ * 是否是闰年
+ */
+ static bool isLeapYear(int year) {
+ return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
+ }
+
+ /**
+ * 本月的第几周
+ */
+ static int getIndexWeekInMonth(DateTime dateTime) {
+ DateTime firstdayInMonth = new DateTime(dateTime.year, dateTime.month, 1);
+ Duration duration = dateTime.difference(firstdayInMonth);
+ return (duration.inDays / 7).toInt() + 1;
+ }
+
+ /**
+ * 本周的第几天
+ */
+ static int getIndexDayInWeek(DateTime dateTime) {
+ DateTime firstdayInMonth = new DateTime(
+ dateTime.year,
+ dateTime.month,
+ );
+ Duration duration = dateTime.difference(firstdayInMonth);
+ return (duration.inDays / 7).toInt() + 1;
+ }
+
+ /**
+ * 本月第一天,是那一周的第几天,从1开始
+ * @return 获取日期所在月视图对应的起始偏移量 the start diff with MonthView
+ */
+ static int getIndexOfFirstDayInMonth(DateTime dateTime) {
+ DateTime firstDayOfMonth = new DateTime(dateTime.year, dateTime.month, 1);
+
+ int week = firstDayOfMonth.weekday;
+
+ return week;
+ }
+
+ static List initCalendarForMonthView(
+ int year, int month, DateTime currentDate, int weekStart,
+ {DateModel minSelectDate,
+ DateModel maxSelectDate,
+ Map extraDataMap}) {
+ weekStart = DateTime.monday;
+ //获取月视图其实偏移量
+ int mPreDiff = getIndexOfFirstDayInMonth(new DateTime(year, month));
+ //获取该月的天数
+ int monthDayCount = getMonthDaysCount(year, month);
+
+ print("$year年$month月,有$monthDayCount天,第一天的index为${mPreDiff}");
+
+ List result = new List();
+
+ int size = 42;
+
+ DateTime firstDayOfMonth = new DateTime(year, month, 1);
+ DateTime lastDayOfMonth = new DateTime(year, month, monthDayCount);
+
+ for (int i = 0; i < size; i++) {
+ DateTime temp;
+ DateModel dateModel;
+ if (i < mPreDiff - 1) {
+ temp = firstDayOfMonth.subtract(Duration(days: mPreDiff - i - 1));
+
+ dateModel = DateModel.fromDateTime(temp);
+ //这个上一月的几天
+ } else if (i >= monthDayCount + (mPreDiff - 1)) {
+ temp = lastDayOfMonth
+ .add(Duration(days: i - mPreDiff - monthDayCount + 2));
+ dateModel = DateModel.fromDateTime(temp);
+ //这是下一月的几天
+ } else {
+ //这个月的
+ temp = new DateTime(year, month, i - mPreDiff + 2);
+ dateModel = DateModel.fromDateTime(temp);
+ }
+
+ //判断是否在范围内
+ if (dateModel.getDateTime().isAfter(minSelectDate.getDateTime()) &&
+ dateModel.getDateTime().isBefore(maxSelectDate.getDateTime())) {
+ dateModel.isInRange = true;
+ } else {
+ dateModel.isInRange = false;
+ }
+ //将自定义额外的数据,存储到相应的model中
+ if (extraDataMap != null && extraDataMap.isNotEmpty) {
+ DateTime dateTime = dateModel.getDateTime();
+ if (extraDataMap.containsKey(dateTime)) {
+ dateModel.extraData = extraDataMap[dateTime];
+ }
+ }
+
+ result.add(dateModel);
+ }
+
+ return result;
+ }
+
+ /**
+ * 月的行数
+ */
+ static int getMonthViewLineCount(int year, int month) {
+ DateTime firstDayOfMonth = new DateTime(year, month, 1);
+ int monthDayCount = getMonthDaysCount(year, month);
+// DateTime lastDayOfMonth = new DateTime(year, month, monthDayCount);
+
+ int preIndex = firstDayOfMonth.weekday - 1;
+// int lastIndex = lastDayOfMonth.weekday;
+
+ print("$year年$month月:有${((preIndex + monthDayCount) / 7).toInt() + 1}行");
+ return ((preIndex + monthDayCount) / 7).toInt() + 1;
+ }
+}
diff --git a/flutter_custom_calendar/lib/utils/lunar_util.dart b/flutter_custom_calendar/lib/utils/lunar_util.dart
new file mode 100644
index 0000000..0676cd2
--- /dev/null
+++ b/flutter_custom_calendar/lib/utils/lunar_util.dart
@@ -0,0 +1,1071 @@
+import 'package:flutter_custom_calendar/constants/constants.dart';
+import 'package:flutter_custom_calendar/model/date_model.dart';
+import 'package:flutter_custom_calendar/utils/date_util.dart';
+import 'package:flutter_custom_calendar/utils/solar_term_util.dart';
+
+/**
+ * 农历的工具类
+ */
+class LunarUtil {
+ static List LUNAR_MONTH_DAYS = [
+ 1887,
+ 0x1694,
+ 0x16aa,
+ 0x4ad5,
+ 0xab6,
+ 0xc4b7,
+ 0x4ae,
+ 0xa56,
+ 0xb52a,
+ 0x1d2a,
+ 0xd54,
+ 0x75aa,
+ 0x156a,
+ 0x1096d,
+ 0x95c,
+ 0x14ae,
+ 0xaa4d,
+ 0x1a4c,
+ 0x1b2a,
+ 0x8d55,
+ 0xad4,
+ 0x135a,
+ 0x495d,
+ 0x95c,
+ 0xd49b,
+ 0x149a,
+ 0x1a4a,
+ 0xbaa5,
+ 0x16a8,
+ 0x1ad4,
+ 0x52da,
+ 0x12b6,
+ 0xe937,
+ 0x92e,
+ 0x1496,
+ 0xb64b,
+ 0xd4a,
+ 0xda8,
+ 0x95b5,
+ 0x56c,
+ 0x12ae,
+ 0x492f,
+ 0x92e,
+ 0xcc96,
+ 0x1a94,
+ 0x1d4a,
+ 0xada9,
+ 0xb5a,
+ 0x56c,
+ 0x726e,
+ 0x125c,
+ 0xf92d,
+ 0x192a,
+ 0x1a94,
+ 0xdb4a,
+ 0x16aa,
+ 0xad4,
+ 0x955b,
+ 0x4ba,
+ 0x125a,
+ 0x592b,
+ 0x152a,
+ 0xf695,
+ 0xd94,
+ 0x16aa,
+ 0xaab5,
+ 0x9b4,
+ 0x14b6,
+ 0x6a57,
+ 0xa56,
+ 0x1152a,
+ 0x1d2a,
+ 0xd54,
+ 0xd5aa,
+ 0x156a,
+ 0x96c,
+ 0x94ae,
+ 0x14ae,
+ 0xa4c,
+ 0x7d26,
+ 0x1b2a,
+ 0xeb55,
+ 0xad4,
+ 0x12da,
+ 0xa95d,
+ 0x95a,
+ 0x149a,
+ 0x9a4d,
+ 0x1a4a,
+ 0x11aa5,
+ 0x16a8,
+ 0x16d4,
+ 0xd2da,
+ 0x12b6,
+ 0x936,
+ 0x9497,
+ 0x1496,
+ 0x1564b,
+ 0xd4a,
+ 0xda8,
+ 0xd5b4,
+ 0x156c,
+ 0x12ae,
+ 0xa92f,
+ 0x92e,
+ 0xc96,
+ 0x6d4a,
+ 0x1d4a,
+ 0x10d65,
+ 0xb58,
+ 0x156c,
+ 0xb26d,
+ 0x125c,
+ 0x192c,
+ 0x9a95,
+ 0x1a94,
+ 0x1b4a,
+ 0x4b55,
+ 0xad4,
+ 0xf55b,
+ 0x4ba,
+ 0x125a,
+ 0xb92b,
+ 0x152a,
+ 0x1694,
+ 0x96aa,
+ 0x15aa,
+ 0x12ab5,
+ 0x974,
+ 0x14b6,
+ 0xca57,
+ 0xa56,
+ 0x1526,
+ 0x8e95,
+ 0xd54,
+ 0x15aa,
+ 0x49b5,
+ 0x96c,
+ 0xd4ae,
+ 0x149c,
+ 0x1a4c,
+ 0xbd26,
+ 0x1aa6,
+ 0xb54,
+ 0x6d6a,
+ 0x12da,
+ 0x1695d,
+ 0x95a,
+ 0x149a,
+ 0xda4b,
+ 0x1a4a,
+ 0x1aa4,
+ 0xbb54,
+ 0x16b4,
+ 0xada,
+ 0x495b,
+ 0x936,
+ 0xf497,
+ 0x1496,
+ 0x154a,
+ 0xb6a5,
+ 0xda4,
+ 0x15b4,
+ 0x6ab6,
+ 0x126e,
+ 0x1092f,
+ 0x92e,
+ 0xc96,
+ 0xcd4a,
+ 0x1d4a,
+ 0xd64,
+ 0x956c,
+ 0x155c,
+ 0x125c,
+ 0x792e,
+ 0x192c,
+ 0xfa95,
+ 0x1a94,
+ 0x1b4a,
+ 0xab55,
+ 0xad4,
+ 0x14da,
+ 0x8a5d,
+ 0xa5a,
+ 0x1152b,
+ 0x152a,
+ 0x1694,
+ 0xd6aa,
+ 0x15aa,
+ 0xab4,
+ 0x94ba,
+ 0x14b6,
+ 0xa56,
+ 0x7527,
+ 0xd26,
+ 0xee53,
+ 0xd54,
+ 0x15aa,
+ 0xa9b5,
+ 0x96c,
+ 0x14ae,
+ 0x8a4e,
+ 0x1a4c,
+ 0x11d26,
+ 0x1aa4,
+ 0x1b54,
+ 0xcd6a,
+ 0xada,
+ 0x95c,
+ 0x949d,
+ 0x149a,
+ 0x1a2a,
+ 0x5b25,
+ 0x1aa4,
+ 0xfb52,
+ 0x16b4,
+ 0xaba,
+ 0xa95b,
+ 0x936,
+ 0x1496,
+ 0x9a4b,
+ 0x154a,
+ 0x136a5,
+ 0xda4,
+ 0x15ac
+ ];
+
+ static List SOLAR = [
+ 1887,
+ 0xec04c,
+ 0xec23f,
+ 0xec435,
+ 0xec649,
+ 0xec83e,
+ 0xeca51,
+ 0xecc46,
+ 0xece3a,
+ 0xed04d,
+ 0xed242,
+ 0xed436,
+ 0xed64a,
+ 0xed83f,
+ 0xeda53,
+ 0xedc48,
+ 0xede3d,
+ 0xee050,
+ 0xee244,
+ 0xee439,
+ 0xee64d,
+ 0xee842,
+ 0xeea36,
+ 0xeec4a,
+ 0xeee3e,
+ 0xef052,
+ 0xef246,
+ 0xef43a,
+ 0xef64e,
+ 0xef843,
+ 0xefa37,
+ 0xefc4b,
+ 0xefe41,
+ 0xf0054,
+ 0xf0248,
+ 0xf043c,
+ 0xf0650,
+ 0xf0845,
+ 0xf0a38,
+ 0xf0c4d,
+ 0xf0e42,
+ 0xf1037,
+ 0xf124a,
+ 0xf143e,
+ 0xf1651,
+ 0xf1846,
+ 0xf1a3a,
+ 0xf1c4e,
+ 0xf1e44,
+ 0xf2038,
+ 0xf224b,
+ 0xf243f,
+ 0xf2653,
+ 0xf2848,
+ 0xf2a3b,
+ 0xf2c4f,
+ 0xf2e45,
+ 0xf3039,
+ 0xf324d,
+ 0xf3442,
+ 0xf3636,
+ 0xf384a,
+ 0xf3a3d,
+ 0xf3c51,
+ 0xf3e46,
+ 0xf403b,
+ 0xf424e,
+ 0xf4443,
+ 0xf4638,
+ 0xf484c,
+ 0xf4a3f,
+ 0xf4c52,
+ 0xf4e48,
+ 0xf503c,
+ 0xf524f,
+ 0xf5445,
+ 0xf5639,
+ 0xf584d,
+ 0xf5a42,
+ 0xf5c35,
+ 0xf5e49,
+ 0xf603e,
+ 0xf6251,
+ 0xf6446,
+ 0xf663b,
+ 0xf684f,
+ 0xf6a43,
+ 0xf6c37,
+ 0xf6e4b,
+ 0xf703f,
+ 0xf7252,
+ 0xf7447,
+ 0xf763c,
+ 0xf7850,
+ 0xf7a45,
+ 0xf7c39,
+ 0xf7e4d,
+ 0xf8042,
+ 0xf8254,
+ 0xf8449,
+ 0xf863d,
+ 0xf8851,
+ 0xf8a46,
+ 0xf8c3b,
+ 0xf8e4f,
+ 0xf9044,
+ 0xf9237,
+ 0xf944a,
+ 0xf963f,
+ 0xf9853,
+ 0xf9a47,
+ 0xf9c3c,
+ 0xf9e50,
+ 0xfa045,
+ 0xfa238,
+ 0xfa44c,
+ 0xfa641,
+ 0xfa836,
+ 0xfaa49,
+ 0xfac3d,
+ 0xfae52,
+ 0xfb047,
+ 0xfb23a,
+ 0xfb44e,
+ 0xfb643,
+ 0xfb837,
+ 0xfba4a,
+ 0xfbc3f,
+ 0xfbe53,
+ 0xfc048,
+ 0xfc23c,
+ 0xfc450,
+ 0xfc645,
+ 0xfc839,
+ 0xfca4c,
+ 0xfcc41,
+ 0xfce36,
+ 0xfd04a,
+ 0xfd23d,
+ 0xfd451,
+ 0xfd646,
+ 0xfd83a,
+ 0xfda4d,
+ 0xfdc43,
+ 0xfde37,
+ 0xfe04b,
+ 0xfe23f,
+ 0xfe453,
+ 0xfe648,
+ 0xfe83c,
+ 0xfea4f,
+ 0xfec44,
+ 0xfee38,
+ 0xff04c,
+ 0xff241,
+ 0xff436,
+ 0xff64a,
+ 0xff83e,
+ 0xffa51,
+ 0xffc46,
+ 0xffe3a,
+ 0x10004e,
+ 0x100242,
+ 0x100437,
+ 0x10064b,
+ 0x100841,
+ 0x100a53,
+ 0x100c48,
+ 0x100e3c,
+ 0x10104f,
+ 0x101244,
+ 0x101438,
+ 0x10164c,
+ 0x101842,
+ 0x101a35,
+ 0x101c49,
+ 0x101e3d,
+ 0x102051,
+ 0x102245,
+ 0x10243a,
+ 0x10264e,
+ 0x102843,
+ 0x102a37,
+ 0x102c4b,
+ 0x102e3f,
+ 0x103053,
+ 0x103247,
+ 0x10343b,
+ 0x10364f,
+ 0x103845,
+ 0x103a38,
+ 0x103c4c,
+ 0x103e42,
+ 0x104036,
+ 0x104249,
+ 0x10443d,
+ 0x104651,
+ 0x104846,
+ 0x104a3a,
+ 0x104c4e,
+ 0x104e43,
+ 0x105038,
+ 0x10524a,
+ 0x10543e,
+ 0x105652,
+ 0x105847,
+ 0x105a3b,
+ 0x105c4f,
+ 0x105e45,
+ 0x106039,
+ 0x10624c,
+ 0x106441,
+ 0x106635,
+ 0x106849,
+ 0x106a3d,
+ 0x106c51,
+ 0x106e47,
+ 0x10703c,
+ 0x10724f,
+ 0x107444,
+ 0x107638,
+ 0x10784c,
+ 0x107a3f,
+ 0x107c53,
+ 0x107e48
+ ];
+
+ /**
+ * 保存每年24节气
+ */
+ static final Map> SOLAR_TERMS = new Map();
+
+ /**
+ * 公历节日
+ */
+ static List SOLAR_CALENDAR = [
+ "0101元旦",
+ "0214情人节",
+ "0308妇女节",
+ "0312植树节",
+ "0315消权日",
+ "0401愚人节",
+ "0422地球日",
+ "0501劳动节",
+ "0504青年节",
+ "0601儿童节",
+ "0701建党节",
+ "0801建军节",
+ "0910教师节",
+ "1001国庆节",
+ "1031万圣节",
+ "1111光棍节",
+ "1224平安夜",
+ "1225圣诞节",
+ ];
+
+ /**
+ * 传统农历节日
+ */
+ static List TRADITION_FESTIVAL_STR = [
+ "除夕",
+ "0101春节",
+ "0115元宵",
+ "0505端午",
+ "0707七夕",
+ "0815中秋",
+ "0909重阳",
+ ];
+
+ /**
+ * 特殊节日、母亲节和父亲节,感恩节等
+ */
+ static final Map> SPECIAL_FESTIVAL = new Map();
+
+ /**
+ * 特殊节日的数组
+ */
+ static List SPECIAL_FESTIVAL_STR = [
+ "母亲节",
+ "父亲节",
+ "感恩节",
+ ];
+
+ /**
+ * 用来表示1900年到2099年间农历年份的相关信息,共24位bit的16进制表示,其中:
+ * 1. 前4位表示该年闰哪个月;
+ * 2. 5-17位表示农历年份13个月的大小月分布,0表示小,1表示大;
+ * 3. 最后7位表示农历年首(正月初一)对应的公历日期。
+ *
+ * 以2014年的数据0x955ABF为例说明:
+ * 1001 0101 0101 1010 1011 1111
+ * 闰九月 农历正月初一对应公历1月31号
+ */
+ static final List LUNAR_INFO = [
+ 0x84B6BF,
+ /*1900*/
+ 0x04AE53,
+ 0x0A5748,
+ 0x5526BD,
+ 0x0D2650,
+ 0x0D9544,
+ 0x46AAB9,
+ 0x056A4D,
+ 0x09AD42,
+ 0x24AEB6,
+ 0x04AE4A,
+ /*1901-1910*/
+ 0x6A4DBE,
+ 0x0A4D52,
+ 0x0D2546,
+ 0x5D52BA,
+ 0x0B544E,
+ 0x0D6A43,
+ 0x296D37,
+ 0x095B4B,
+ 0x749BC1,
+ 0x049754,
+ /*1911-1920*/
+ 0x0A4B48,
+ 0x5B25BC,
+ 0x06A550,
+ 0x06D445,
+ 0x4ADAB8,
+ 0x02B64D,
+ 0x095742,
+ 0x2497B7,
+ 0x04974A,
+ 0x664B3E,
+ /*1921-1930*/
+ 0x0D4A51,
+ 0x0EA546,
+ 0x56D4BA,
+ 0x05AD4E,
+ 0x02B644,
+ 0x393738,
+ 0x092E4B,
+ 0x7C96BF,
+ 0x0C9553,
+ 0x0D4A48,
+ /*1931-1940*/
+ 0x6DA53B,
+ 0x0B554F,
+ 0x056A45,
+ 0x4AADB9,
+ 0x025D4D,
+ 0x092D42,
+ 0x2C95B6,
+ 0x0A954A,
+ 0x7B4ABD,
+ 0x06CA51,
+ /*1941-1950*/
+ 0x0B5546,
+ 0x555ABB,
+ 0x04DA4E,
+ 0x0A5B43,
+ 0x352BB8,
+ 0x052B4C,
+ 0x8A953F,
+ 0x0E9552,
+ 0x06AA48,
+ 0x6AD53C,
+ /*1951-1960*/
+ 0x0AB54F,
+ 0x04B645,
+ 0x4A5739,
+ 0x0A574D,
+ 0x052642,
+ 0x3E9335,
+ 0x0D9549,
+ 0x75AABE,
+ 0x056A51,
+ 0x096D46,
+ /*1961-1970*/
+ 0x54AEBB,
+ 0x04AD4F,
+ 0x0A4D43,
+ 0x4D26B7,
+ 0x0D254B,
+ 0x8D52BF,
+ 0x0B5452,
+ 0x0B6A47,
+ 0x696D3C,
+ 0x095B50,
+ /*1971-1980*/
+ 0x049B45,
+ 0x4A4BB9,
+ 0x0A4B4D,
+ 0xAB25C2,
+ 0x06A554,
+ 0x06D449,
+ 0x6ADA3D,
+ 0x0AB651,
+ 0x095746,
+ 0x5497BB,
+ /*1981-1990*/
+ 0x04974F,
+ 0x064B44,
+ 0x36A537,
+ 0x0EA54A,
+ 0x86B2BF,
+ 0x05AC53,
+ 0x0AB647,
+ 0x5936BC,
+ 0x092E50,
+ 0x0C9645,
+ /*1991-2000*/
+ 0x4D4AB8,
+ 0x0D4A4C,
+ 0x0DA541,
+ 0x25AAB6,
+ 0x056A49,
+ 0x7AADBD,
+ 0x025D52,
+ 0x092D47,
+ 0x5C95BA,
+ 0x0A954E,
+ /*2001-2010*/
+ 0x0B4A43,
+ 0x4B5537,
+ 0x0AD54A,
+ 0x955ABF,
+ 0x04BA53,
+ 0x0A5B48,
+ 0x652BBC,
+ 0x052B50,
+ 0x0A9345,
+ 0x474AB9,
+ /*2011-2020*/
+ 0x06AA4C,
+ 0x0AD541,
+ 0x24DAB6,
+ 0x04B64A,
+ 0x6a573D,
+ 0x0A4E51,
+ 0x0D2646,
+ 0x5E933A,
+ 0x0D534D,
+ 0x05AA43,
+ /*2021-2030*/
+ 0x36B537,
+ 0x096D4B,
+ 0xB4AEBF,
+ 0x04AD53,
+ 0x0A4D48,
+ 0x6D25BC,
+ 0x0D254F,
+ 0x0D5244,
+ 0x5DAA38,
+ 0x0B5A4C,
+ /*2031-2040*/
+ 0x056D41,
+ 0x24ADB6,
+ 0x049B4A,
+ 0x7A4BBE,
+ 0x0A4B51,
+ 0x0AA546,
+ 0x5B52BA,
+ 0x06D24E,
+ 0x0ADA42,
+ 0x355B37,
+ /*2041-2050*/
+ 0x09374B,
+ 0x8497C1,
+ 0x049753,
+ 0x064B48,
+ 0x66A53C,
+ 0x0EA54F,
+ 0x06AA44,
+ 0x4AB638,
+ 0x0AAE4C,
+ 0x092E42,
+ /*2051-2060*/
+ 0x3C9735,
+ 0x0C9649,
+ 0x7D4ABD,
+ 0x0D4A51,
+ 0x0DA545,
+ 0x55AABA,
+ 0x056A4E,
+ 0x0A6D43,
+ 0x452EB7,
+ 0x052D4B,
+ /*2061-2070*/
+ 0x8A95BF,
+ 0x0A9553,
+ 0x0B4A47,
+ 0x6B553B,
+ 0x0AD54F,
+ 0x055A45,
+ 0x4A5D38,
+ 0x0A5B4C,
+ 0x052B42,
+ 0x3A93B6,
+ /*2071-2080*/
+ 0x069349,
+ 0x7729BD,
+ 0x06AA51,
+ 0x0AD546,
+ 0x54DABA,
+ 0x04B64E,
+ 0x0A5743,
+ 0x452738,
+ 0x0D264A,
+ 0x8E933E,
+ /*2081-2090*/
+ 0x0D5252,
+ 0x0DAA47,
+ 0x66B53B,
+ 0x056D4F,
+ 0x04AE45,
+ 0x4A4EB9,
+ 0x0A4D4C,
+ 0x0D1541,
+ 0x2D92B5 /*2091-2099*/
+ ];
+
+ /**
+ * 初始化各种农历、节日
+ *
+ * @param calendar calendar
+ */
+ static void setupLunarCalendar(DateModel dateModel) {
+ int year = dateModel.year;
+ int month = dateModel.month;
+ int day = dateModel.day;
+
+ dateModel.isWeekend = DateUtil.isWeekend(new DateTime(year, month, day));
+ dateModel.isLeapYear = DateUtil.isLeapYear(year);
+ dateModel.isCurrentDay = DateUtil.isCurrentDay(year, month, day);
+
+ List lunar = LunarUtil.solarToLunar(year, month, day);
+
+ dateModel.lunarYear = (lunar[0]);
+ dateModel.lunarMonth = (lunar[1]);
+ dateModel.lunarDay = (lunar[2]);
+
+ if (lunar[3] == 1) {
+ //如果是闰月
+ dateModel.leapMonth = lunar[1];
+ }
+ //24节气
+ String solarTerm = getSolarTerm(year, month, day);
+ dateModel.solarTerm=solarTerm;
+ //公历节日
+ String gregorian = gregorianFestival(month, day);
+ dateModel.gregorianFestival=gregorian;
+ //传统农历节日
+ String festival = getTraditionFestival(lunar[0], lunar[1], lunar[2]);
+ dateModel.traditionFestival=festival;
+ //农历格式的日期
+ String lunarText = numToChinese(lunar[1], lunar[2], lunar[3]);
+
+ if (gregorian.isEmpty) {
+ gregorian = getSpecialFestival(year, month, day);
+ }
+ if (solarTerm.isNotEmpty) {
+ dateModel.lunarString = solarTerm;
+ } else if (gregorian.isNotEmpty) {
+ dateModel.lunarString = gregorian;
+ } else if (festival.isNotEmpty) {
+ dateModel.lunarString = festival;
+ } else {
+ dateModel.lunarString = lunarText;
+ }
+ }
+
+ /**
+ * 公历转农历 Solar To Lunar
+ *
+ * @param year 公历年
+ * @param month 公历月
+ * @param day 公历日
+ * @return [0]农历年 [1]农历月 [2]农历日 [3]是否闰月 0 false : 1 true
+ */
+ static List solarToLunar(int year, int month, int day) {
+ List lunarInt = new List(4);
+ int index = year - SOLAR[0];
+ int data = (year << 9) | (month << 5) | (day);
+ int solar11;
+ if (SOLAR[index] > data) {
+ index--;
+ }
+ solar11 = SOLAR[index];
+ int y = getBitInt(solar11, 12, 9);
+ int m = getBitInt(solar11, 4, 5);
+ int d = getBitInt(solar11, 5, 0);
+ int offset = solarToInt(year, month, day) - solarToInt(y, m, d);
+
+ int days = LUNAR_MONTH_DAYS[index];
+ int leap = getBitInt(days, 4, 13);
+
+ int lunarY = index + SOLAR[0];
+ int lunarM = 1;
+ int lunarD;
+ offset += 1;
+
+ for (int i = 0; i < 13; i++) {
+ int dm = getBitInt(days, 1, 12 - i) == 1 ? 30 : 29;
+ if (offset > dm) {
+ lunarM++;
+ offset -= dm;
+ } else {
+ break;
+ }
+ }
+
+ lunarD = offset;
+ lunarInt[0] = lunarY;
+ lunarInt[1] = lunarM;
+ lunarInt[3] = 0;
+
+ if (leap != 0 && lunarM > leap) {
+ lunarInt[1] = lunarM - 1;
+ if (lunarM == leap + 1) {
+ lunarInt[3] = 1;
+ }
+ }
+ lunarInt[2] = lunarD;
+ return lunarInt;
+ }
+
+ static int getBitInt(int data, int length, int shift) {
+ return (data & (((1 << length) - 1) << shift)) >> shift;
+ }
+
+ static int solarToInt(int y, int m, int d) {
+ m = (m + 9) % 12;
+ y = y - (m / 10).toInt();
+ return (365 * y +
+ (y / 4).toInt() -
+ (y / 100).toInt() +
+ (y / 400).toInt() +
+ ((m * 306 + 5) / 10).toInt() +
+ (d - 1));
+ }
+
+ /**
+ * 返回24节气
+ *
+ * @param year 年
+ * @param month 月
+ * @param day 日
+ * @return 返回24节气
+ */
+ static String getSolarTerm(int year, int month, int day) {
+ if (!SOLAR_TERMS.containsKey(year)) {
+ SOLAR_TERMS.addAll({year: SolarTermUtil.getSolarTerms(year)});
+ }
+ List solarTerm = SOLAR_TERMS[year];
+ String text = "${year}" + getString(month, day);
+ String solar = "";
+ for (String solarTermName in solarTerm) {
+ if (solarTermName.contains(text)) {
+ solar = solarTermName.replaceAll(text, "");
+ break;
+ }
+ }
+ return solar;
+ }
+
+ /**
+ * 数字转换为农历节日或者日期
+ *
+ * @param month 月
+ * @param day 日
+ * @param leap 1==闰月
+ * @return 数字转换为汉字日
+ */
+ static String numToChinese(int month, int day, int leap) {
+ if (day == 1) {
+ return numToChineseMonth(month, leap);
+ }
+ return Constants.LUNAR_DAY_TEXT[day - 1];
+ }
+
+ /**
+ * 数字转换为汉字月份
+ *
+ * @param month 月
+ * @param leap 1==闰月
+ * @return 数字转换为汉字月份
+ */
+ static String numToChineseMonth(int month, int leap) {
+ if (leap == 1) {
+ return "闰" + Constants.LUNAR_MONTH_TEXT[month - 1];
+ }
+ return Constants.LUNAR_MONTH_TEXT[month - 1];
+ }
+
+ static String getString(int month, int day) {
+ return (month >= 10 ? month.toString() : "0$month") +
+ (day >= 10 ? day.toString() : "0$day");
+ }
+
+ /**
+ * 获取公历节日
+ *
+ * @param month 公历月份
+ * @param day 公历日期
+ * @return 公历节日
+ */
+ static String gregorianFestival(int month, int day) {
+ String text = getString(month, day);
+ String solar = "";
+ for (String aMSolarCalendar in SOLAR_CALENDAR) {
+ if (aMSolarCalendar.contains(text)) {
+ solar = aMSolarCalendar.replaceAll(text, "");
+ break;
+ }
+ }
+ return solar;
+ }
+
+ /**
+ * 返回传统农历节日
+ *
+ * @param year 农历年
+ * @param month 农历月
+ * @param day 农历日
+ * @return 返回传统农历节日
+ */
+ static String getTraditionFestival(int year, int month, int day) {
+ if (month == 12) {
+ int count = daysInLunarMonth(year, month);
+ if (day == count) {
+ return TRADITION_FESTIVAL_STR[0]; //除夕
+ }
+ }
+ String text = getString(month, day);
+ String festivalStr = "";
+ for (String festival in TRADITION_FESTIVAL_STR) {
+ if (festival.contains(text)) {
+ festivalStr = festival.replaceAll(text, "");
+ break;
+ }
+ }
+ return festivalStr;
+ }
+
+ /**
+ * 传回农历 year年month月的总天数,总共有13个月包括闰月
+ *
+ * @param year 将要计算的年份
+ * @param month 将要计算的月份
+ * @return 传回农历 year年month月的总天数
+ */
+ static int daysInLunarMonth(int year, int month) {
+ if ((LUNAR_INFO[year - 1900] & (0x100000 >> month)) == 0)
+ return 29;
+ else
+ return 30;
+ }
+
+ /**
+ * 获取特殊计算方式的节日
+ * 如:每年五月的第二个星期日为母亲节,六月的第三个星期日为父亲节
+ * 每年11月第四个星期四定为"感恩节"
+ *
+ * @param year year
+ * @param month month
+ * @param day day
+ * @return 获取西方节日
+ */
+ static String getSpecialFestival(int year, int month, int day) {
+ if (!SPECIAL_FESTIVAL.containsKey(year)) {
+ SPECIAL_FESTIVAL.addAll({year: getSpecialFestivals(year)});
+ }
+ List specialFestivals = SPECIAL_FESTIVAL[year];
+ String text = "$year" + getString(month, day);
+ String solar = "";
+ for (String special in specialFestivals) {
+ if (special.contains(text)) {
+ solar = special.replaceAll(text, "");
+ break;
+ }
+ }
+ return solar;
+ }
+
+ /**
+ * 获取每年的母亲节和父亲节和感恩节
+ * 特殊计算方式的节日
+ *
+ * @param year 年
+ * @return 获取每年的母亲节和父亲节、感恩节
+ */
+ static List getSpecialFestivals(int year) {
+ List festivals = new List(3);
+ DateTime dateTime = new DateTime(year, 5, 1);
+
+ //母亲节
+ int week = (dateTime.weekday + 1) % 8;
+ int startDiff = 7 - week + 1;
+ if (startDiff == 7) {
+ festivals[0] =
+ dateToString(year, 5, startDiff + 1) + SPECIAL_FESTIVAL_STR[0];
+ } else {
+ festivals[0] =
+ dateToString(year, 5, startDiff + 7 + 1) + SPECIAL_FESTIVAL_STR[0];
+ }
+
+ //父亲节
+ dateTime = new DateTime(year, 6, 1);
+
+ week = (dateTime.weekday + 1) % 8;
+ startDiff = 7 - week + 1;
+ if (startDiff == 7) {
+ festivals[1] =
+ dateToString(year, 6, startDiff + 7 + 1) + SPECIAL_FESTIVAL_STR[1];
+ } else {
+ festivals[1] = dateToString(year, 6, startDiff + 7 + 7 + 1) +
+ SPECIAL_FESTIVAL_STR[1];
+ }
+
+ //感恩节
+ dateTime = new DateTime(year, 11, 1);
+ week = (dateTime.weekday + 1) % 8;
+
+ startDiff = 7 - week + 1;
+ if (startDiff <= 2) {
+ festivals[2] =
+ dateToString(year, 11, startDiff + 21 + 5) + SPECIAL_FESTIVAL_STR[2];
+ } else {
+ festivals[2] =
+ dateToString(year, 11, startDiff + 14 + 5) + SPECIAL_FESTIVAL_STR[2];
+ }
+ return festivals;
+ }
+
+ static String dateToString(int year, int month, int day) {
+ return "$year" + getString(month, day);
+ }
+}
diff --git a/flutter_custom_calendar/lib/utils/math_util.dart b/flutter_custom_calendar/lib/utils/math_util.dart
new file mode 100644
index 0000000..a817d6b
--- /dev/null
+++ b/flutter_custom_calendar/lib/utils/math_util.dart
@@ -0,0 +1,22 @@
+class Math {
+ static double abs(double num) {
+ if (num < 0) {
+ return -num;
+ } else {
+ return num;
+ }
+ }
+}
+
+class System {
+//todo:后面再检查这个方法是否正确
+// src:源数组;
+// srcPos:源数组要复制的起始位置;
+// dest:目的数组;
+// destPos:目的数组放置的起始位置;
+// length:复制的长度。
+ static void arraycopy(List src, int srcPos, List dest,
+ int destPos, int length) {
+ List.copyRange(dest, destPos, src, srcPos, srcPos+length);
+ }
+}
diff --git a/flutter_custom_calendar/lib/utils/solar_term_util.dart b/flutter_custom_calendar/lib/utils/solar_term_util.dart
new file mode 100644
index 0000000..9320df0
--- /dev/null
+++ b/flutter_custom_calendar/lib/utils/solar_term_util.dart
@@ -0,0 +1,2230 @@
+import 'dart:core';
+import 'dart:math';
+
+import 'package:flutter_custom_calendar/utils/math_util.dart';
+
+/**
+ * http://www.cnblogs.com/moodlxs/archive/2010/12/18/2345392.html
+ * 24节气计算公式,参考该博客实现
+ */
+class SolarTermUtil {
+ /**
+ * 24节气
+ */
+ static List SOLAR_TERMS = [
+ "春分",
+ "清明",
+ "谷雨",
+ "立夏",
+ "小满",
+ "芒种",
+ "夏至",
+ "小暑",
+ "大暑",
+ "立秋",
+ "处暑",
+ "白露",
+ "秋分",
+ "寒露",
+ "霜降",
+ "立冬",
+ "小雪",
+ "大雪",
+ "冬至",
+ "小寒",
+ "大寒",
+ "立春",
+ "雨水",
+ "惊蛰",
+ ];
+
+ /**
+ * 每弧度的角秒数
+ */
+ static final double SECOND_PER_RAD = 180 * 3600 / pi;
+
+ /**
+ * 每弧度的角度数
+ */
+ static final double ANGLE_PER_RAD = 180 / pi;
+
+ /**
+ * 日历计算
+ * 2000年前儒略日数(2000-1-1)
+ */
+ static final double J2000 = 2451545;
+
+ /**
+ * 黄赤交角系数表
+ */
+ static final List H_C_ANGLE_TABLE = [
+ 0,
+ 50287.92262,
+ 111.24406,
+ 0.07699,
+ -0.23479,
+ -0.00178,
+ 0.00018,
+ 0.00001
+ ];
+
+ /**
+ * 世界时与原子时之差计算表
+ */
+ static final List DTS = [
+ -4000,
+ 108371.7,
+ -13036.80,
+ 392.000,
+ 0.0000,
+ -500,
+ 17201.0,
+ -627.82,
+ 16.170,
+ -0.3413,
+ -150,
+ 12200.6,
+ -346.41,
+ 5.403,
+ -0.1593,
+ 150,
+ 9113.8,
+ -328.13,
+ -1.647,
+ 0.0377,
+ 500,
+ 5707.5,
+ -391.41,
+ 0.915,
+ 0.3145,
+ 900,
+ 2203.4,
+ -283.45,
+ 13.034,
+ -0.1778,
+ 1300,
+ 490.1,
+ -57.35,
+ 2.085,
+ -0.0072,
+ 1600,
+ 120.0,
+ -9.81,
+ -1.532,
+ 0.1403,
+ 1700,
+ 10.2,
+ -0.91,
+ 0.510,
+ -0.0370,
+ 1800,
+ 13.4,
+ -0.72,
+ 0.202,
+ -0.0193,
+ 1830,
+ 7.8,
+ -1.81,
+ 0.416,
+ -0.0247,
+ 1860,
+ 8.3,
+ -0.13,
+ -0.406,
+ 0.0292,
+ 1880,
+ -5.4,
+ 0.32,
+ -0.183,
+ 0.0173,
+ 1900,
+ -2.3,
+ 2.06,
+ 0.169,
+ -0.0135,
+ 1920,
+ 21.2,
+ 1.69,
+ -0.304,
+ 0.0167,
+ 1940,
+ 24.2,
+ 1.22,
+ -0.064,
+ 0.0031,
+ 1960,
+ 33.2,
+ 0.51,
+ 0.231,
+ -0.0109,
+ 1980,
+ 51.0,
+ 1.29,
+ -0.026,
+ 0.0032,
+ 2000,
+ 64.7,
+ -1.66,
+ 5.224,
+ -0.2905,
+ 2150,
+ 279.4,
+ 732.95,
+ 429.579,
+ 0.0158,
+ 6000
+ ];
+
+ /**
+ * 离心率
+ */
+ static final List GXC_E = [0.016708634, -0.000042037, -0.0000001267];
+
+ /**
+ * 近点
+ */
+ static final List GXC_P = [
+ 102.93735 / ANGLE_PER_RAD,
+ 1.71946 / ANGLE_PER_RAD,
+ 0.00046 / ANGLE_PER_RAD
+ ];
+
+ /**
+ * 太平黄经
+ */
+ static final List GXC_L = [
+ 280.4664567 / ANGLE_PER_RAD,
+ 36000.76982779 / ANGLE_PER_RAD,
+ 0.0003032028 / ANGLE_PER_RAD,
+ 1 / 49931000 / ANGLE_PER_RAD,
+ -1 / 153000000 / ANGLE_PER_RAD
+ ];
+
+ /**
+ * 光行差常数
+ */
+ static final double GXC_K = 20.49552 / SECOND_PER_RAD;
+
+ /**
+ * 向下取整
+ *
+ * @param v v
+ * @return 取整数部分
+ */
+ static double doubleFloor(double v) {
+ if (v < 0) return v + 1;
+
+ return v;
+ }
+
+ /**
+ * 对超过0-2PI的角度转为0-2PI
+ *
+ * @param v v
+ * @return 对超过0-2PI的角度转为0-2PI
+ */
+ static double rad2mrad(double v) {
+ v = v % (2 * pi);
+ if (v < 0) return v + 2 * pi;
+
+ return v;
+ }
+
+ /**
+ * 计算世界时与原子时之差,传入年
+ *
+ * @param year 年
+ * @return 计算世界时与原子时之差
+ */
+ static double worldTimeDiff(double year) {
+ int i;
+ for (i = 0; i < 100; i += 5) if (year < DTS[i + 5] || i == 95) break;
+
+ double t1 = (year - DTS[i]) / (DTS[i + 5] - DTS[i]) * 10;
+ double t2 = t1 * t1;
+ double t3 = t2 * t1;
+ return DTS[i + 1] + DTS[i + 2] * t1 + DTS[i + 3] * t2 + DTS[i + 4] * t3;
+ }
+
+ /**
+ * 传入儒略日(J2000起算),计算UTC与原子时的差(单位:日)
+ *
+ * @param julian 儒略日
+ * @return 计算UTC与原子时的差
+ */
+ static double atomTimeDiff(double julian) {
+ return worldTimeDiff(julian / 365.2425 + 2000) / 86400.0;
+ }
+
+ /**
+ * 公历转儒略日,UTC=1表示原日期是UTC
+ *
+ * @param UTC UTC
+ * @return 公历转儒略日, UTC=1表示原日期是UTC
+ */
+ static double toJulian(Time time, bool UTC) {
+ double y = time.year; // 取出年月
+ double m = time.month;
+ double n = 0;
+
+ if (m <= 2) {
+ m += 12;
+ y--;
+ }
+
+ if (time.year * 372 + time.month * 31 + time.day >= 588829) {
+// 判断是否为格里高利历日1582*372+10*31+15
+ n = doubleFloor(y / 100);
+ n = 2 - n + doubleFloor(n / 4); // 加百年闰
+ }
+
+ n += doubleFloor(365.2500001 * (y + 4716)); // 加上年引起的偏移日数
+ n += doubleFloor(30.6 * (m + 1)) + time.day; // 加上月引起的偏移日数及日偏移数
+ n += ((time.second / 60 + time.minute) / 60 + time.hour) / 24 - 1524.5;
+ if (UTC) return n + atomTimeDiff(n - J2000);
+
+ return n;
+ }
+
+ /**
+ * 儒略日数转公历,UTC=1表示目标公历是UTC
+ *
+ * @param jd jd
+ * @param UTC UTC
+ */
+ static Time setFromJulian(double jd, bool UTC) {
+ Time time = new Time();
+ if (UTC) jd -= atomTimeDiff(jd - J2000);
+
+ jd += 0.5;
+
+// 取得日数的整数部份A及小数部分F
+ double A = doubleFloor(jd);
+ double F = jd - A;
+ double D;
+
+ if (A > 2299161) {
+ D = doubleFloor((A - 1867216.25) / 36524.25);
+ A += 1 + D - doubleFloor(D / 4);
+ }
+ A += 1524; // 向前移4年零2个月
+ time.year = doubleFloor((A - 122.1) / 365.25); // 年
+ D = A - doubleFloor(365.25 * time.year); // 去除整年日数后余下日数
+ time.month = doubleFloor(D / 30.6001); // 月数
+ time.day = D - doubleFloor(time.month * 30.6001); // 去除整月日数后余下日数
+ time.year -= 4716;
+ time.month--;
+ if (time.month > 12) time.month -= 12;
+ if (time.month <= 2) time.year++;
+// 日的小数转为时分秒
+ F *= 24;
+ time.hour = doubleFloor(F);
+ F -= time.hour;
+ F *= 60;
+ time.minute = doubleFloor(F);
+ F -= time.minute;
+ F *= 60;
+ time.second = F;
+ return time;
+ }
+
+ /**
+ * 补岁差
+ *
+ * @param jd jd
+ * @param zb zb
+ */
+ static void precession(double jd, List zb) {
+ int i;
+ double t = 1, v = 0, t1 = jd / 365250;
+ for (i = 1; i < 8; i++) {
+ t *= t1;
+ v += H_C_ANGLE_TABLE[i] * t;
+ }
+ zb[0] = rad2mrad(zb[0] + (v + 2.9965 * t1) / SECOND_PER_RAD);
+ }
+
+ /**
+ * 恒星周年光行差计算(黄道坐标中)
+ *
+ * @param t t
+ * @param zb zb
+ */
+ static void addGxc(double t, List zb) {
+ double t1 = t / 36525;
+ double t2 = t1 * t1;
+ double t3 = t2 * t1;
+ double t4 = t3 * t1;
+ double L = GXC_L[0] +
+ GXC_L[1] * t1 +
+ GXC_L[2] * t2 +
+ GXC_L[3] * t3 +
+ GXC_L[4] * t4;
+ double p = GXC_P[0] + GXC_P[1] * t1 + GXC_P[2] * t2;
+ double e = GXC_E[0] + GXC_E[1] * t1 + GXC_E[2] * t2;
+ double dL = L - zb[0], dP = p - zb[0];
+ zb[0] -= GXC_K * (cos(dL) - e * cos(dP)) / cos(zb[1]);
+ zb[1] -= GXC_K * sin(zb[1]) * (sin(dL) - e * sin(dP));
+ zb[0] = rad2mrad(zb[0]);
+ }
+
+ /**
+ * 章动计算
+ */
+ static final List nutB = [
+ // 章动表
+ 2.1824391966, -33.757045954, 0.0000362262, 3.7340E-08, -2.8793E-10,
+ -171996, -1742, 92025, 89, 3.5069406862, 1256.663930738,
+ 0.0000105845, 6.9813E-10, -2.2815E-10, -13187, -16, 5736, -31,
+ 1.3375032491, 16799.418221925, -0.0000511866, 6.4626E-08,
+ -5.3543E-10, -2274, -2, 977, -5, 4.3648783932, -67.514091907,
+ 0.0000724525, 7.4681E-08, -5.7586E-10, 2062, 2, -895, 5,
+ 0.0431251803, -628.301955171, 0.0000026820, 6.5935E-10, 5.5705E-11,
+ -1426, 34, 54, -1, 2.3555557435, 8328.691425719, 0.0001545547,
+ 2.5033E-07, -1.1863E-09, 712, 1, -7, 0, 3.4638155059,
+ 1884.965885909, 0.0000079025, 3.8785E-11, -2.8386E-10, -517, 12,
+ 224, -6, 5.4382493597, 16833.175267879, -0.0000874129, 2.7285E-08,
+ -2.4750E-10, -386, -4, 200, 0, 3.6930589926, 25128.109647645,
+ 0.0001033681, 3.1496E-07, -1.7218E-09, -301, 0, 129, -1,
+ 3.5500658664, 628.361975567, 0.0000132664, 1.3575E-09, -1.7245E-10,
+ 217, -5, -95, 3
+ ];
+
+ /**
+ * 计算黄经章动及交角章动
+ *
+ * @param t t
+ * @return 计算黄经章动及交角章动
+ */
+ static Nutation nutation(double t) {
+ Nutation d = new Nutation();
+ d.Lon = 0;
+ d.Obl = 0;
+ t /= 36525;
+ double c, t1 = t, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1; // t5=t4*t1;
+ for (int i = 0; i < nutB.length; i += 9) {
+ c = nutB[i] +
+ nutB[i + 1] * t1 +
+ nutB[i + 2] * t2 +
+ nutB[i + 3] * t3 +
+ nutB[i + 4] * t4;
+ d.Lon += (nutB[i + 5] + nutB[i + 6] * t / 10) * sin(c); // 黄经章动
+ d.Obl += (nutB[i + 7] + nutB[i + 8] * t / 10) * cos(c); // 交角章动
+ }
+ d.Lon /= SECOND_PER_RAD * 10000; // 黄经章动
+ d.Obl /= SECOND_PER_RAD * 10000; // 交角章动
+ return d;
+ }
+
+ /***************************************
+ * 如果用记事本查看此代码,请在"格式"菜单中去除"自动换行"
+ * E10是关于地球的,格式如下:
+ * 它是一个数组,每3个数看作一条记录,每条记录的3个数记为A,B,C
+ * rec=A*cos(B+C*t); 式中t是J2000起算的儒略千年数
+ * 每条记录的计算结果(即rec)取和即得地球的日心黄经的周期量L0
+ * E11格式如下: rec = A*cos*(B+C*t) *t, 取和后得泊松量L1
+ * E12格式如下: rec = A*cos*(B+C*t) *t*t, 取和后得泊松量L2
+ * E13格式如下: rec = A*cos*(B+C*t) *t*t*t, 取和后得泊松量L3
+ * 最后地球的地心黄经:L = L0+L1+L2+L3+...
+ * E20,E21,E22,E23...用于计算黄纬
+ * M10,M11等是关于月球的,参数的用法请阅读Mnn()函数
+ *****************************************/
+//地球运动VSOP87参数
+ static final List E10 = [
+ //黄经周期项
+ 1.75347045673,
+ 0.00000000000,
+ 0.0000000000,
+ 0.03341656456,
+ 4.66925680417,
+ 6283.0758499914,
+ 0.00034894275,
+ 4.62610241759,
+ 12566.1516999828,
+ 0.00003417571,
+ 2.82886579606,
+ 3.5231183490,
+ 0.00003497056,
+ 2.74411800971,
+ 5753.3848848968,
+ 0.00003135896,
+ 3.62767041758,
+ 77713.7714681205,
+ 0.00002676218,
+ 4.41808351397,
+ 7860.4193924392,
+ 0.00002342687,
+ 6.13516237631,
+ 3930.2096962196,
+ 0.00001273166,
+ 2.03709655772,
+ 529.6909650946,
+ 0.00001324292,
+ 0.74246356352,
+ 11506.7697697936,
+ 0.00000901855,
+ 2.04505443513,
+ 26.2983197998,
+ 0.00001199167,
+ 1.10962944315,
+ 1577.3435424478,
+ 0.00000857223,
+ 3.50849156957,
+ 398.1490034082,
+ 0.00000779786,
+ 1.17882652114,
+ 5223.6939198022,
+ 0.00000990250,
+ 5.23268129594,
+ 5884.9268465832,
+ 0.00000753141,
+ 2.53339053818,
+ 5507.5532386674,
+ 0.00000505264,
+ 4.58292563052,
+ 18849.2275499742,
+ 0.00000492379,
+ 4.20506639861,
+ 775.5226113240,
+ 0.00000356655,
+ 2.91954116867,
+ 0.0673103028,
+ 0.00000284125,
+ 1.89869034186,
+ 796.2980068164,
+ 0.00000242810,
+ 0.34481140906,
+ 5486.7778431750,
+ 0.00000317087,
+ 5.84901952218,
+ 11790.6290886588,
+ 0.00000271039,
+ 0.31488607649,
+ 10977.0788046990,
+ 0.00000206160,
+ 4.80646606059,
+ 2544.3144198834,
+ 0.00000205385,
+ 1.86947813692,
+ 5573.1428014331,
+ 0.00000202261,
+ 2.45767795458,
+ 6069.7767545534,
+ 0.00000126184,
+ 1.08302630210,
+ 20.7753954924,
+ 0.00000155516,
+ 0.83306073807,
+ 213.2990954380,
+ 0.00000115132,
+ 0.64544911683,
+ 0.9803210682,
+ 0.00000102851,
+ 0.63599846727,
+ 4694.0029547076,
+ 0.00000101724,
+ 4.26679821365,
+ 7.1135470008,
+ 0.00000099206,
+ 6.20992940258,
+ 2146.1654164752,
+ 0.00000132212,
+ 3.41118275555,
+ 2942.4634232916,
+ 0.00000097607,
+ 0.68101272270,
+ 155.4203994342,
+ 0.00000085128,
+ 1.29870743025,
+ 6275.9623029906,
+ 0.00000074651,
+ 1.75508916159,
+ 5088.6288397668,
+ 0.00000101895,
+ 0.97569221824,
+ 15720.8387848784,
+ 0.00000084711,
+ 3.67080093025,
+ 71430.6956181291,
+ 0.00000073547,
+ 4.67926565481,
+ 801.8209311238,
+ 0.00000073874,
+ 3.50319443167,
+ 3154.6870848956,
+ 0.00000078756,
+ 3.03698313141,
+ 12036.4607348882,
+ 0.00000079637,
+ 1.80791330700,
+ 17260.1546546904,
+ 0.00000085803,
+ 5.98322631256,
+ 161000.6857376741,
+ 0.00000056963,
+ 2.78430398043,
+ 6286.5989683404,
+ 0.00000061148,
+ 1.81839811024,
+ 7084.8967811152,
+ 0.00000069627,
+ 0.83297596966,
+ 9437.7629348870,
+ 0.00000056116,
+ 4.38694880779,
+ 14143.4952424306,
+ 0.00000062449,
+ 3.97763880587,
+ 8827.3902698748,
+ 0.00000051145,
+ 0.28306864501,
+ 5856.4776591154,
+ 0.00000055577,
+ 3.47006009062,
+ 6279.5527316424,
+ 0.00000041036,
+ 5.36817351402,
+ 8429.2412664666,
+ 0.00000051605,
+ 1.33282746983,
+ 1748.0164130670,
+ 0.00000051992,
+ 0.18914945834,
+ 12139.5535091068,
+ 0.00000049000,
+ 0.48735065033,
+ 1194.4470102246,
+ 0.00000039200,
+ 6.16832995016,
+ 10447.3878396044,
+ 0.00000035566,
+ 1.77597314691,
+ 6812.7668150860,
+ 0.00000036770,
+ 6.04133859347,
+ 10213.2855462110,
+ 0.00000036596,
+ 2.56955238628,
+ 1059.3819301892,
+ 0.00000033291,
+ 0.59309499459,
+ 17789.8456197850,
+ 0.00000035954,
+ 1.70876111898,
+ 2352.8661537718
+ ];
+ static final List E11 = [
+ //黄经泊松1项
+ 6283.31966747491,
+ 0.00000000000,
+ 0.0000000000,
+ 0.00206058863,
+ 2.67823455584,
+ 6283.0758499914,
+ 0.00004303430,
+ 2.63512650414,
+ 12566.1516999828,
+ 0.00000425264,
+ 1.59046980729,
+ 3.5231183490,
+ 0.00000108977,
+ 2.96618001993,
+ 1577.3435424478,
+ 0.00000093478,
+ 2.59212835365,
+ 18849.2275499742,
+ 0.00000119261,
+ 5.79557487799,
+ 26.2983197998,
+ 0.00000072122,
+ 1.13846158196,
+ 529.6909650946,
+ 0.00000067768,
+ 1.87472304791,
+ 398.1490034082,
+ 0.00000067327,
+ 4.40918235168,
+ 5507.5532386674,
+ 0.00000059027,
+ 2.88797038460,
+ 5223.6939198022,
+ 0.00000055976,
+ 2.17471680261,
+ 155.4203994342,
+ 0.00000045407,
+ 0.39803079805,
+ 796.2980068164,
+ 0.00000036369,
+ 0.46624739835,
+ 775.5226113240,
+ 0.00000028958,
+ 2.64707383882,
+ 7.1135470008,
+ 0.00000019097,
+ 1.84628332577,
+ 5486.7778431750,
+ 0.00000020844,
+ 5.34138275149,
+ 0.9803210682,
+ 0.00000018508,
+ 4.96855124577,
+ 213.2990954380,
+ 0.00000016233,
+ 0.03216483047,
+ 2544.3144198834,
+ 0.00000017293,
+ 2.99116864949,
+ 6275.9623029906
+ ];
+ static final List E12 = [
+ //黄经泊松2项
+ 0.00052918870,
+ 0.00000000000,
+ 0.0000000000,
+ 0.00008719837,
+ 1.07209665242,
+ 6283.0758499914,
+ 0.00000309125,
+ 0.86728818832,
+ 12566.1516999828,
+ 0.00000027339,
+ 0.05297871691,
+ 3.5231183490,
+ 0.00000016334,
+ 5.18826691036,
+ 26.2983197998,
+ 0.00000015752,
+ 3.68457889430,
+ 155.4203994342,
+ 0.00000009541,
+ 0.75742297675,
+ 18849.2275499742,
+ 0.00000008937,
+ 2.05705419118,
+ 77713.7714681205,
+ 0.00000006952,
+ 0.82673305410,
+ 775.5226113240,
+ 0.00000005064,
+ 4.66284525271,
+ 1577.3435424478
+ ];
+ static final List E13 = [
+ 0.00000289226,
+ 5.84384198723,
+ 6283.0758499914,
+ 0.00000034955,
+ 0.00000000000,
+ 0.0000000000,
+ 0.00000016819,
+ 5.48766912348,
+ 12566.1516999828
+ ];
+ static final List E14 = [
+ 0.00000114084,
+ 3.14159265359,
+ 0.0000000000,
+ 0.00000007717,
+ 4.13446589358,
+ 6283.0758499914,
+ 0.00000000765,
+ 3.83803776214,
+ 12566.1516999828
+ ];
+ static final List E15 = [0.00000000878, 3.14159265359, 0.0000000000];
+ static final List E20 = [
+ //黄纬周期项
+ 0.00000279620,
+ 3.19870156017,
+ 84334.6615813083,
+ 0.00000101643,
+ 5.42248619256,
+ 5507.5532386674,
+ 0.00000080445,
+ 3.88013204458,
+ 5223.6939198022,
+ 0.00000043806,
+ 3.70444689758,
+ 2352.8661537718,
+ 0.00000031933,
+ 4.00026369781,
+ 1577.3435424478,
+ 0.00000022724,
+ 3.98473831560,
+ 1047.7473117547,
+ 0.00000016392,
+ 3.56456119782,
+ 5856.4776591154,
+ 0.00000018141,
+ 4.98367470263,
+ 6283.0758499914,
+ 0.00000014443,
+ 3.70275614914,
+ 9437.7629348870,
+ 0.00000014304,
+ 3.41117857525,
+ 10213.2855462110
+ ];
+ static final List E21 = [
+ 0.00000009030,
+ 3.89729061890,
+ 5507.5532386674,
+ 0.00000006177,
+ 1.73038850355,
+ 5223.6939198022
+ ];
+ static final List E30 = [
+ //距离周期项
+ 1.00013988799,
+ 0.00000000000,
+ 0.0000000000,
+ 0.01670699626,
+ 3.09846350771,
+ 6283.0758499914,
+ 0.00013956023,
+ 3.05524609620,
+ 12566.1516999828,
+ 0.00003083720,
+ 5.19846674381,
+ 77713.7714681205,
+ 0.00001628461,
+ 1.17387749012,
+ 5753.3848848968,
+ 0.00001575568,
+ 2.84685245825,
+ 7860.4193924392,
+ 0.00000924799,
+ 5.45292234084,
+ 11506.7697697936,
+ 0.00000542444,
+ 4.56409149777,
+ 3930.2096962196
+ ];
+ static final List E31 = [
+ 0.00103018608,
+ 1.10748969588,
+ 6283.0758499914,
+ 0.00001721238,
+ 1.06442301418,
+ 12566.1516999828,
+ 0.00000702215,
+ 3.14159265359,
+ 0.0000000000
+ ];
+ static final List E32 = [
+ 0.00004359385,
+ 5.78455133738,
+ 6283.0758499914
+ ];
+ static final List E33 = [
+ 0.00000144595,
+ 4.27319435148,
+ 6283.0758499914
+ ];
+
+//月球运动参数
+ static final List M10 = [
+ 22639.5858800,
+ 2.3555545723,
+ 8328.6914247251,
+ 1.5231275E-04,
+ 2.5041111E-07,
+ -1.1863391E-09,
+ 4586.4383203,
+ 8.0413790709,
+ 7214.0628654588,
+ -2.1850087E-04,
+ -1.8646419E-07,
+ 8.7760973E-10,
+ 2369.9139357,
+ 10.3969336431,
+ 15542.7542901840,
+ -6.6188121E-05,
+ 6.3946925E-08,
+ -3.0872935E-10,
+ 769.0257187,
+ 4.7111091445,
+ 16657.3828494503,
+ 3.0462550E-04,
+ 5.0082223E-07,
+ -2.3726782E-09,
+ -666.4175399,
+ -0.0431256817,
+ 628.3019552485,
+ -2.6638815E-06,
+ 6.1639211E-10,
+ -5.4439728E-11,
+ -411.5957339,
+ 3.2558104895,
+ 16866.9323152810,
+ -1.2804259E-04,
+ -9.8998954E-09,
+ 4.0433461E-11,
+ 211.6555524,
+ 5.6858244986,
+ -1114.6285592663,
+ -3.7081362E-04,
+ -4.3687530E-07,
+ 2.0639488E-09,
+ 205.4359530,
+ 8.0845047526,
+ 6585.7609102104,
+ -2.1583699E-04,
+ -1.8708058E-07,
+ 9.3204945E-10,
+ 191.9561973,
+ 12.7524882154,
+ 23871.4457149091,
+ 8.6124629E-05,
+ 3.1435804E-07,
+ -1.4950684E-09,
+ 164.7286185,
+ 10.4400593249,
+ 14914.4523349355,
+ -6.3524240E-05,
+ 6.3330532E-08,
+ -2.5428962E-10,
+ -147.3213842,
+ -2.3986802540,
+ -7700.3894694766,
+ -1.5497663E-04,
+ -2.4979472E-07,
+ 1.1318993E-09,
+ -124.9881185,
+ 5.1984668216,
+ 7771.3771450920,
+ -3.3094061E-05,
+ 3.1973462E-08,
+ -1.5436468E-10,
+ -109.3803637,
+ 2.3124288905,
+ 8956.9933799736,
+ 1.4964887E-04,
+ 2.5102751E-07,
+ -1.2407788E-09,
+ 55.1770578,
+ 7.1411231536,
+ -1324.1780250970,
+ 6.1854469E-05,
+ 7.3846820E-08,
+ -3.4916281E-10,
+ -45.0996092,
+ 5.6113650618,
+ 25195.6237400061,
+ 2.4270161E-05,
+ 2.4051122E-07,
+ -1.1459056E-09,
+ 39.5333010,
+ -0.9002559173,
+ -8538.2408905558,
+ 2.8035534E-04,
+ 2.6031101E-07,
+ -1.2267725E-09,
+ 38.4298346,
+ 18.4383127140,
+ 22756.8171556428,
+ -2.8468899E-04,
+ -1.2251727E-07,
+ 5.6888037E-10,
+ 36.1238141,
+ 7.0666637168,
+ 24986.0742741754,
+ 4.5693825E-04,
+ 7.5123334E-07,
+ -3.5590172E-09,
+ 30.7725751,
+ 16.0827581417,
+ 14428.1257309177,
+ -4.3700174E-04,
+ -3.7292838E-07,
+ 1.7552195E-09,
+ -28.3971008,
+ 7.9982533891,
+ 7842.3648207073,
+ -2.2116475E-04,
+ -1.8584780E-07,
+ 8.2317000E-10,
+ -24.3582283,
+ 10.3538079614,
+ 16171.0562454324,
+ -6.8852003E-05,
+ 6.4563317E-08,
+ -3.6316908E-10,
+ -18.5847068,
+ 2.8429122493,
+ -557.3142796331,
+ -1.8540681E-04,
+ -2.1843765E-07,
+ 1.0319744E-09,
+ 17.9544674,
+ 5.1553411398,
+ 8399.6791003405,
+ -3.5757942E-05,
+ 3.2589854E-08,
+ -2.0880440E-10,
+ 14.5302779,
+ 12.7956138971,
+ 23243.1437596606,
+ 8.8788511E-05,
+ 3.1374165E-07,
+ -1.4406287E-09,
+ 14.3796974,
+ 15.1080427876,
+ 32200.1371396342,
+ 2.3843738E-04,
+ 5.6476915E-07,
+ -2.6814075E-09,
+ 14.2514576,
+ -24.0810366320,
+ -2.3011998397,
+ 1.5231275E-04,
+ 2.5041111E-07,
+ -1.1863391E-09,
+ 13.8990596,
+ 20.7938672862,
+ 31085.5085803679,
+ -1.3237624E-04,
+ 1.2789385E-07,
+ -6.1745870E-10,
+ 13.1940636,
+ 3.3302699264,
+ -9443.3199839914,
+ -5.2312637E-04,
+ -6.8728642E-07,
+ 3.2502879E-09,
+ -9.6790568,
+ -4.7542348263,
+ -16029.0808942018,
+ -3.0728938E-04,
+ -5.0020584E-07,
+ 2.3182384E-09,
+ -9.3658635,
+ 11.2971895604,
+ 24080.9951807398,
+ -3.4654346E-04,
+ -1.9636409E-07,
+ 9.1804319E-10,
+ 8.6055318,
+ 5.7289501804,
+ -1742.9305145148,
+ -3.6814974E-04,
+ -4.3749170E-07,
+ 2.1183885E-09,
+ -8.4530982,
+ 7.5540213938,
+ 16100.0685698171,
+ 1.1921869E-04,
+ 2.8238458E-07,
+ -1.3407038E-09,
+ 8.0501724,
+ 10.4831850066,
+ 14286.1503796870,
+ -6.0860358E-05,
+ 6.2714140E-08,
+ -1.9984990E-10,
+ -7.6301553,
+ 4.6679834628,
+ 17285.6848046987,
+ 3.0196162E-04,
+ 5.0143862E-07,
+ -2.4271179E-09,
+ -7.4474952,
+ -0.0862513635,
+ 1256.6039104970,
+ -5.3277630E-06,
+ 1.2327842E-09,
+ -1.0887946E-10,
+ 7.3712011,
+ 8.1276304344,
+ 5957.4589549619,
+ -2.1317311E-04,
+ -1.8769697E-07,
+ 9.8648918E-10,
+ 7.0629900,
+ 0.9591375719,
+ 33.7570471374,
+ -3.0829302E-05,
+ -3.6967043E-08,
+ 1.7385419E-10,
+ -6.3831491,
+ 9.4966777258,
+ 7004.5133996281,
+ 2.1416722E-04,
+ 3.2425793E-07,
+ -1.5355019E-09,
+ -5.7416071,
+ 13.6527441326,
+ 32409.6866054649,
+ -1.9423071E-04,
+ 5.4047029E-08,
+ -2.6829589E-10,
+ 4.3740095,
+ 18.4814383957,
+ 22128.5152003943,
+ -2.8202511E-04,
+ -1.2313366E-07,
+ 6.2332010E-10,
+ -3.9976134,
+ 7.9669196340,
+ 33524.3151647312,
+ 1.7658291E-04,
+ 4.9092233E-07,
+ -2.3322447E-09,
+ -3.2096876,
+ 13.2398458924,
+ 14985.4400105508,
+ -2.5159493E-04,
+ -1.5449073E-07,
+ 7.2324505E-10,
+ -2.9145404,
+ 12.7093625336,
+ 24499.7476701576,
+ 8.3460748E-05,
+ 3.1497443E-07,
+ -1.5495082E-09,
+ 2.7318890,
+ 16.1258838235,
+ 13799.8237756692,
+ -4.3433786E-04,
+ -3.7354477E-07,
+ 1.8096592E-09,
+ -2.5679459,
+ -2.4418059357,
+ -7072.0875142282,
+ -1.5764051E-04,
+ -2.4917833E-07,
+ 1.0774596E-09,
+ -2.5211990,
+ 7.9551277074,
+ 8470.6667759558,
+ -2.2382863E-04,
+ -1.8523141E-07,
+ 7.6873027E-10,
+ 2.4888871,
+ 5.6426988169,
+ -486.3266040178,
+ -3.7347750E-04,
+ -4.3625891E-07,
+ 2.0095091E-09,
+ 2.1460741,
+ 7.1842488353,
+ -1952.4799803455,
+ 6.4518350E-05,
+ 7.3230428E-08,
+ -2.9472308E-10,
+ 1.9777270,
+ 23.1494218585,
+ 39414.2000050930,
+ 1.9936508E-05,
+ 3.7830496E-07,
+ -1.8037978E-09,
+ 1.9336825,
+ 9.4222182890,
+ 33314.7656989005,
+ 6.0925100E-04,
+ 1.0016445E-06,
+ -4.7453563E-09,
+ 1.8707647,
+ 20.8369929680,
+ 30457.2066251194,
+ -1.2971236E-04,
+ 1.2727746E-07,
+ -5.6301898E-10,
+ -1.7529659,
+ 0.4873576771,
+ -8886.0057043583,
+ -3.3771956E-04,
+ -4.6884877E-07,
+ 2.2183135E-09,
+ -1.4371624,
+ 7.0979974718,
+ -695.8760698485,
+ 5.9190587E-05,
+ 7.4463212E-08,
+ -4.0360254E-10,
+ -1.3725701,
+ 1.4552986550,
+ -209.5494658307,
+ 4.3266809E-04,
+ 5.1072212E-07,
+ -2.4131116E-09,
+ 1.2618162,
+ 7.5108957121,
+ 16728.3705250656,
+ 1.1655481E-04,
+ 2.8300097E-07,
+ -1.3951435E-09
+ ];
+ static final List M11 = [
+ 1.6768000,
+ -0.0431256817,
+ 628.3019552485,
+ -2.6638815E-06,
+ 6.1639211E-10,
+ -5.4439728E-11,
+ 0.5164200,
+ 11.2260974062,
+ 6585.7609102104,
+ -2.1583699E-04,
+ -1.8708058E-07,
+ 9.3204945E-10,
+ 0.4138300,
+ 13.5816519784,
+ 14914.4523349355,
+ -6.3524240E-05,
+ 6.3330532E-08,
+ -2.5428962E-10,
+ 0.3711500,
+ 5.5402729076,
+ 7700.3894694766,
+ 1.5497663E-04,
+ 2.4979472E-07,
+ -1.1318993E-09,
+ 0.2756000,
+ 2.3124288905,
+ 8956.9933799736,
+ 1.4964887E-04,
+ 2.5102751E-07,
+ -1.2407788E-09,
+ 0.2459863,
+ -25.6198212459,
+ -2.3011998397,
+ 1.5231275E-04,
+ 2.5041111E-07,
+ -1.1863391E-09,
+ 0.0711800,
+ 7.9982533891,
+ 7842.3648207073,
+ -2.2116475E-04,
+ -1.8584780E-07,
+ 8.2317000E-10,
+ 0.0612800,
+ 10.3538079614,
+ 16171.0562454324,
+ -6.8852003E-05,
+ 6.4563317E-08,
+ -3.6316908E-10
+ ];
+ static final List M12 = [
+ 0.0048700,
+ -0.0431256817,
+ 628.3019552485,
+ -2.6638815E-06,
+ 6.1639211E-10,
+ -5.4439728E-11,
+ 0.0022800,
+ -27.1705318325,
+ -2.3011998397,
+ 1.5231275E-04,
+ 2.5041111E-07,
+ -1.1863391E-09,
+ 0.0015000,
+ 11.2260974062,
+ 6585.7609102104,
+ -2.1583699E-04,
+ -1.8708058E-07,
+ 9.3204945E-10
+ ];
+ static final List M20 = [
+ 18461.2400600,
+ 1.6279052448,
+ 8433.4661576405,
+ -6.4021295E-05,
+ -4.9499477E-09,
+ 2.0216731E-11,
+ 1010.1671484,
+ 3.9834598170,
+ 16762.1575823656,
+ 8.8291456E-05,
+ 2.4546117E-07,
+ -1.1661223E-09,
+ 999.6936555,
+ 0.7276493275,
+ -104.7747329154,
+ 2.1633405E-04,
+ 2.5536106E-07,
+ -1.2065558E-09,
+ 623.6524746,
+ 8.7690283983,
+ 7109.2881325435,
+ -2.1668263E-06,
+ 6.8896872E-08,
+ -3.2894608E-10,
+ 199.4837596,
+ 9.6692843156,
+ 15647.5290230993,
+ -2.8252217E-04,
+ -1.9141414E-07,
+ 8.9782646E-10,
+ 166.5741153,
+ 6.4134738261,
+ -1219.4032921817,
+ -1.5447958E-04,
+ -1.8151424E-07,
+ 8.5739300E-10,
+ 117.2606951,
+ 12.0248388879,
+ 23976.2204478244,
+ -1.3020942E-04,
+ 5.8996977E-08,
+ -2.8851262E-10,
+ 61.9119504,
+ 6.3390143893,
+ 25090.8490070907,
+ 2.4060421E-04,
+ 4.9587228E-07,
+ -2.3524614E-09,
+ 33.3572027,
+ 11.1245829706,
+ 15437.9795572686,
+ 1.5014592E-04,
+ 3.1930799E-07,
+ -1.5152852E-09,
+ 31.7596709,
+ 3.0832038997,
+ 8223.9166918098,
+ 3.6864680E-04,
+ 5.0577218E-07,
+ -2.3928949E-09,
+ 29.5766003,
+ 8.8121540801,
+ 6480.9861772950,
+ 4.9705523E-07,
+ 6.8280480E-08,
+ -2.7450635E-10,
+ 15.5662654,
+ 4.0579192538,
+ -9548.0947169068,
+ -3.0679233E-04,
+ -4.3192536E-07,
+ 2.0437321E-09,
+ 15.1215543,
+ 14.3803934601,
+ 32304.9118725496,
+ 2.2103334E-05,
+ 3.0940809E-07,
+ -1.4748517E-09,
+ -12.0941511,
+ 8.7259027166,
+ 7737.5900877920,
+ -4.8307078E-06,
+ 6.9513264E-08,
+ -3.8338581E-10,
+ 8.8681426,
+ 9.7124099974,
+ 15019.2270678508,
+ -2.7985829E-04,
+ -1.9203053E-07,
+ 9.5226618E-10,
+ 8.0450400,
+ 0.6687636586,
+ 8399.7091105030,
+ -3.3191993E-05,
+ 3.2017096E-08,
+ -1.5363746E-10,
+ 7.9585542,
+ 12.0679645696,
+ 23347.9184925760,
+ -1.2754553E-04,
+ 5.8380585E-08,
+ -2.3407289E-10,
+ 7.4345550,
+ 6.4565995078,
+ -1847.7052474301,
+ -1.5181570E-04,
+ -1.8213063E-07,
+ 9.1183272E-10,
+ -6.7314363,
+ -4.0265854988,
+ -16133.8556271171,
+ -9.0955337E-05,
+ -2.4484477E-07,
+ 1.1116826E-09,
+ 6.5795750,
+ 16.8104074692,
+ 14323.3509980023,
+ -2.2066770E-04,
+ -1.1756732E-07,
+ 5.4866364E-10,
+ -6.4600721,
+ 1.5847795630,
+ 9061.7681128890,
+ -6.6685176E-05,
+ -4.3335556E-09,
+ -3.4222998E-11,
+ -6.2964773,
+ 4.8837157343,
+ 25300.3984729215,
+ -1.9206388E-04,
+ -1.4849843E-08,
+ 6.0650192E-11,
+ -5.6323538,
+ -0.7707750092,
+ 733.0766881638,
+ -2.1899793E-04,
+ -2.5474467E-07,
+ 1.1521161E-09,
+ -5.3683961,
+ 6.8263720663,
+ 16204.8433027325,
+ -9.7115356E-05,
+ 2.7023515E-08,
+ -1.3414795E-10,
+ -5.3112784,
+ 3.9403341353,
+ 17390.4595376141,
+ 8.5627574E-05,
+ 2.4607756E-07,
+ -1.2205621E-09,
+ -5.0759179,
+ 0.6845236457,
+ 523.5272223331,
+ 2.1367016E-04,
+ 2.5597745E-07,
+ -1.2609955E-09,
+ -4.8396143,
+ -1.6710309265,
+ -7805.1642023920,
+ 6.1357413E-05,
+ 5.5663398E-09,
+ -7.4656459E-11,
+ -4.8057401,
+ 3.5705615768,
+ -662.0890125485,
+ 3.0927234E-05,
+ 3.6923410E-08,
+ -1.7458141E-10,
+ 3.9840545,
+ 8.6945689615,
+ 33419.5404318159,
+ 3.9291696E-04,
+ 7.4628340E-07,
+ -3.5388005E-09,
+ 3.6744619,
+ 19.1659620415,
+ 22652.0424227274,
+ -6.8354947E-05,
+ 1.3284380E-07,
+ -6.3767543E-10,
+ 2.9984815,
+ 20.0662179587,
+ 31190.2833132833,
+ -3.4871029E-04,
+ -1.2746721E-07,
+ 5.8909710E-10,
+ 2.7986413,
+ -2.5281611620,
+ -16971.7070481963,
+ 3.4437664E-04,
+ 2.6526096E-07,
+ -1.2469893E-09,
+ 2.4138774,
+ 17.7106633865,
+ 22861.5918885581,
+ -5.0102304E-04,
+ -3.7787833E-07,
+ 1.7754362E-09,
+ 2.1863132,
+ 5.5132179088,
+ -9757.6441827375,
+ 1.2587576E-04,
+ 7.8796768E-08,
+ -3.6937954E-10,
+ 2.1461692,
+ 13.4801375428,
+ 23766.6709819937,
+ 3.0245868E-04,
+ 5.6971910E-07,
+ -2.7016242E-09,
+ 1.7659832,
+ 11.1677086523,
+ 14809.6776020201,
+ 1.5280981E-04,
+ 3.1869159E-07,
+ -1.4608454E-09,
+ -1.6244212,
+ 7.3137297434,
+ 7318.8375983742,
+ -4.3483492E-04,
+ -4.4182525E-07,
+ 2.0841655E-09,
+ 1.5813036,
+ 5.4387584720,
+ 16552.6081165349,
+ 5.2095955E-04,
+ 7.5618329E-07,
+ -3.5792340E-09,
+ 1.5197528,
+ 16.7359480324,
+ 40633.6032972747,
+ 1.7441609E-04,
+ 5.5981921E-07,
+ -2.6611908E-09,
+ 1.5156341,
+ 1.7023646816,
+ -17876.7861416319,
+ -4.5910508E-04,
+ -6.8233647E-07,
+ 3.2300712E-09,
+ 1.5102092,
+ 5.4977296450,
+ 8399.6847301375,
+ -3.3094061E-05,
+ 3.1973462E-08,
+ -1.5436468E-10,
+ -1.3178223,
+ 9.6261586339,
+ 16275.8309783478,
+ -2.8518605E-04,
+ -1.9079775E-07,
+ 8.4338673E-10,
+ -1.2642739,
+ 11.9817132061,
+ 24604.5224030729,
+ -1.3287330E-04,
+ 5.9613369E-08,
+ -3.4295235E-10,
+ 1.1918723,
+ 22.4217725310,
+ 39518.9747380084,
+ -1.9639754E-04,
+ 1.2294390E-07,
+ -5.9724197E-10,
+ 1.1346110,
+ 14.4235191419,
+ 31676.6099173011,
+ 2.4767216E-05,
+ 3.0879170E-07,
+ -1.4204120E-09,
+ 1.0857810,
+ 8.8552797618,
+ 5852.6842220465,
+ 3.1609367E-06,
+ 6.7664088E-08,
+ -2.2006663E-10,
+ -1.0193852,
+ 7.2392703065,
+ 33629.0898976466,
+ -3.9751134E-05,
+ 2.3556127E-07,
+ -1.1256889E-09,
+ -0.8227141,
+ 11.0814572888,
+ 16066.2815125171,
+ 1.4748204E-04,
+ 3.1992438E-07,
+ -1.5697249E-09,
+ 0.8042238,
+ 3.5274358950,
+ -33.7870573000,
+ 2.8263353E-05,
+ 3.7539802E-08,
+ -2.2902113E-10,
+ 0.8025939,
+ 6.7832463846,
+ 16833.1452579809,
+ -9.9779237E-05,
+ 2.7639907E-08,
+ -1.8858767E-10,
+ -0.7931866,
+ -6.3821400710,
+ -24462.5470518423,
+ -2.4326809E-04,
+ -4.9525589E-07,
+ 2.2980217E-09,
+ -0.7910153,
+ 6.3703481443,
+ -591.1013369332,
+ -1.5714346E-04,
+ -1.8089785E-07,
+ 8.0295327E-10,
+ -0.6674056,
+ 9.1819266386,
+ 24533.5347274576,
+ 5.5197395E-05,
+ 2.7743463E-07,
+ -1.3204870E-09,
+ 0.6502226,
+ 4.1010449356,
+ -10176.3966721553,
+ -3.0412845E-04,
+ -4.3254175E-07,
+ 2.0981718E-09,
+ -0.6388131,
+ 6.2958887075,
+ 25719.1509623392,
+ 2.3794032E-04,
+ 4.9648867E-07,
+ -2.4069012E-09
+ ];
+ static final List M21 = [
+ 0.0743000,
+ 11.9537467337,
+ 6480.9861772950,
+ 4.9705523E-07,
+ 6.8280480E-08,
+ -2.7450635E-10,
+ 0.0304300,
+ 8.7259027166,
+ 7737.5900877920,
+ -4.8307078E-06,
+ 6.9513264E-08,
+ -3.8338581E-10,
+ 0.0222900,
+ 12.8540026510,
+ 15019.2270678508,
+ -2.7985829E-04,
+ -1.9203053E-07,
+ 9.5226618E-10,
+ 0.0199900,
+ 15.2095572232,
+ 23347.9184925760,
+ -1.2754553E-04,
+ 5.8380585E-08,
+ -2.3407289E-10,
+ 0.0186900,
+ 9.5981921614,
+ -1847.7052474301,
+ -1.5181570E-04,
+ -1.8213063E-07,
+ 9.1183272E-10,
+ 0.0169600,
+ 7.1681781524,
+ 16133.8556271171,
+ 9.0955337E-05,
+ 2.4484477E-07,
+ -1.1116826E-09,
+ 0.0162300,
+ 1.5847795630,
+ 9061.7681128890,
+ -6.6685176E-05,
+ -4.3335556E-09,
+ -3.4222998E-11,
+ 0.0141900,
+ -0.7707750092,
+ 733.0766881638,
+ -2.1899793E-04,
+ -2.5474467E-07,
+ 1.1521161E-09
+ ];
+ static final List M30 = [
+ 385000.5290396,
+ 1.5707963268,
+ 0.0000000000,
+ 0.0000000E+00,
+ 0.0000000E+00,
+ 0.0000000E+00,
+ -20905.3551378,
+ 3.9263508990,
+ 8328.6914247251,
+ 1.5231275E-04,
+ 2.5041111E-07,
+ -1.1863391E-09,
+ -3699.1109330,
+ 9.6121753977,
+ 7214.0628654588,
+ -2.1850087E-04,
+ -1.8646419E-07,
+ 8.7760973E-10,
+ -2955.9675626,
+ 11.9677299699,
+ 15542.7542901840,
+ -6.6188121E-05,
+ 6.3946925E-08,
+ -3.0872935E-10,
+ -569.9251264,
+ 6.2819054713,
+ 16657.3828494503,
+ 3.0462550E-04,
+ 5.0082223E-07,
+ -2.3726782E-09,
+ 246.1584797,
+ 7.2566208254,
+ -1114.6285592663,
+ -3.7081362E-04,
+ -4.3687530E-07,
+ 2.0639488E-09,
+ -204.5861179,
+ 12.0108556517,
+ 14914.4523349355,
+ -6.3524240E-05,
+ 6.3330532E-08,
+ -2.5428962E-10,
+ -170.7330791,
+ 14.3232845422,
+ 23871.4457149091,
+ 8.6124629E-05,
+ 3.1435804E-07,
+ -1.4950684E-09,
+ -152.1378118,
+ 9.6553010794,
+ 6585.7609102104,
+ -2.1583699E-04,
+ -1.8708058E-07,
+ 9.3204945E-10,
+ -129.6202242,
+ -0.8278839272,
+ -7700.3894694766,
+ -1.5497663E-04,
+ -2.4979472E-07,
+ 1.1318993E-09,
+ 108.7427014,
+ 6.7692631483,
+ 7771.3771450920,
+ -3.3094061E-05,
+ 3.1973462E-08,
+ -1.5436468E-10,
+ 104.7552944,
+ 3.8832252173,
+ 8956.9933799736,
+ 1.4964887E-04,
+ 2.5102751E-07,
+ -1.2407788E-09,
+ 79.6605685,
+ 0.6705404095,
+ -8538.2408905558,
+ 2.8035534E-04,
+ 2.6031101E-07,
+ -1.2267725E-09,
+ 48.8883284,
+ 1.5276706450,
+ 628.3019552485,
+ -2.6638815E-06,
+ 6.1639211E-10,
+ -5.4439728E-11,
+ -34.7825237,
+ 20.0091090408,
+ 22756.8171556428,
+ -2.8468899E-04,
+ -1.2251727E-07,
+ 5.6888037E-10,
+ 30.8238599,
+ 11.9246042882,
+ 16171.0562454324,
+ -6.8852003E-05,
+ 6.4563317E-08,
+ -3.6316908E-10,
+ 24.2084985,
+ 9.5690497159,
+ 7842.3648207073,
+ -2.2116475E-04,
+ -1.8584780E-07,
+ 8.2317000E-10,
+ -23.2104305,
+ 8.6374600436,
+ 24986.0742741754,
+ 4.5693825E-04,
+ 7.5123334E-07,
+ -3.5590172E-09,
+ -21.6363439,
+ 17.6535544685,
+ 14428.1257309177,
+ -4.3700174E-04,
+ -3.7292838E-07,
+ 1.7552195E-09,
+ -16.6747239,
+ 6.7261374666,
+ 8399.6791003405,
+ -3.5757942E-05,
+ 3.2589854E-08,
+ -2.0880440E-10,
+ 14.4026890,
+ 4.9010662531,
+ -9443.3199839914,
+ -5.2312637E-04,
+ -6.8728642E-07,
+ 3.2502879E-09,
+ -12.8314035,
+ 14.3664102239,
+ 23243.1437596606,
+ 8.8788511E-05,
+ 3.1374165E-07,
+ -1.4406287E-09,
+ -11.6499478,
+ 22.3646636130,
+ 31085.5085803679,
+ -1.3237624E-04,
+ 1.2789385E-07,
+ -6.1745870E-10,
+ -10.4447578,
+ 16.6788391144,
+ 32200.1371396342,
+ 2.3843738E-04,
+ 5.6476915E-07,
+ -2.6814075E-09,
+ 10.3211071,
+ 8.7119194804,
+ -1324.1780250970,
+ 6.1854469E-05,
+ 7.3846820E-08,
+ -3.4916281E-10,
+ 10.0562033,
+ 7.2997465071,
+ -1742.9305145148,
+ -3.6814974E-04,
+ -4.3749170E-07,
+ 2.1183885E-09,
+ -9.8844667,
+ 12.0539813334,
+ 14286.1503796870,
+ -6.0860358E-05,
+ 6.2714140E-08,
+ -1.9984990E-10,
+ 8.7515625,
+ 6.3563649081,
+ -9652.8694498221,
+ -9.0458282E-05,
+ -1.7656429E-07,
+ 8.3717626E-10,
+ -8.3791067,
+ 4.4137085761,
+ -557.3142796331,
+ -1.8540681E-04,
+ -2.1843765E-07,
+ 1.0319744E-09,
+ -7.0026961,
+ -3.1834384995,
+ -16029.0808942018,
+ -3.0728938E-04,
+ -5.0020584E-07,
+ 2.3182384E-09,
+ 6.3220032,
+ 9.1248177206,
+ 16100.0685698171,
+ 1.1921869E-04,
+ 2.8238458E-07,
+ -1.3407038E-09,
+ 5.7508579,
+ 6.2387797896,
+ 17285.6848046987,
+ 3.0196162E-04,
+ 5.0143862E-07,
+ -2.4271179E-09,
+ -4.9501349,
+ 9.6984267611,
+ 5957.4589549619,
+ -2.1317311E-04,
+ -1.8769697E-07,
+ 9.8648918E-10,
+ -4.4211770,
+ 3.0260949818,
+ -209.5494658307,
+ 4.3266809E-04,
+ 5.1072212E-07,
+ -2.4131116E-09,
+ 4.1311145,
+ 11.0674740526,
+ 7004.5133996281,
+ 2.1416722E-04,
+ 3.2425793E-07,
+ -1.5355019E-09,
+ -3.9579827,
+ 20.0522347225,
+ 22128.5152003943,
+ -2.8202511E-04,
+ -1.2313366E-07,
+ 6.2332010E-10,
+ 3.2582371,
+ 14.8106422192,
+ 14985.4400105508,
+ -2.5159493E-04,
+ -1.5449073E-07,
+ 7.2324505E-10,
+ -3.1483020,
+ 4.8266068163,
+ 16866.9323152810,
+ -1.2804259E-04,
+ -9.8998954E-09,
+ 4.0433461E-11,
+ 2.6164092,
+ 14.2801588604,
+ 24499.7476701576,
+ 8.3460748E-05,
+ 3.1497443E-07,
+ -1.5495082E-09,
+ 2.3536310,
+ 9.5259240342,
+ 8470.6667759558,
+ -2.2382863E-04,
+ -1.8523141E-07,
+ 7.6873027E-10,
+ -2.1171283,
+ -0.8710096090,
+ -7072.0875142282,
+ -1.5764051E-04,
+ -2.4917833E-07,
+ 1.0774596E-09,
+ -1.8970368,
+ 17.6966801503,
+ 13799.8237756692,
+ -4.3433786E-04,
+ -3.7354477E-07,
+ 1.8096592E-09,
+ -1.7385258,
+ 2.0581540038,
+ -8886.0057043583,
+ -3.3771956E-04,
+ -4.6884877E-07,
+ 2.2183135E-09,
+ -1.5713944,
+ 22.4077892948,
+ 30457.2066251194,
+ -1.2971236E-04,
+ 1.2727746E-07,
+ -5.6301898E-10,
+ -1.4225541,
+ 24.7202181853,
+ 39414.2000050930,
+ 1.9936508E-05,
+ 3.7830496E-07,
+ -1.8037978E-09,
+ -1.4189284,
+ 17.1661967915,
+ 23314.1314352759,
+ -9.9282182E-05,
+ 9.5920387E-08,
+ -4.6309403E-10,
+ 1.1655364,
+ 3.8400995356,
+ 9585.2953352221,
+ 1.4698499E-04,
+ 2.5164390E-07,
+ -1.2952185E-09,
+ -1.1169371,
+ 10.9930146158,
+ 33314.7656989005,
+ 6.0925100E-04,
+ 1.0016445E-06,
+ -4.7453563E-09,
+ 1.0656723,
+ 1.4845449633,
+ 1256.6039104970,
+ -5.3277630E-06,
+ 1.2327842E-09,
+ -1.0887946E-10,
+ 1.0586190,
+ 11.9220903668,
+ 8364.7398411275,
+ -2.1850087E-04,
+ -1.8646419E-07,
+ 8.7760973E-10,
+ -0.9333176,
+ 9.0816920389,
+ 16728.3705250656,
+ 1.1655481E-04,
+ 2.8300097E-07,
+ -1.3951435E-09,
+ 0.8624328,
+ 12.4550876470,
+ 6656.7485858257,
+ -4.0390768E-04,
+ -4.0490184E-07,
+ 1.9095841E-09,
+ 0.8512404,
+ 4.3705828944,
+ 70.9876756153,
+ -1.8807069E-04,
+ -2.1782126E-07,
+ 9.7753467E-10,
+ -0.8488018,
+ 16.7219647962,
+ 31571.8351843857,
+ 2.4110126E-04,
+ 5.6415276E-07,
+ -2.6269678E-09,
+ -0.7956264,
+ 3.5134526588,
+ -9095.5551701890,
+ 9.4948529E-05,
+ 4.1873358E-08,
+ -1.9479814E-10
+ ];
+ static final List M31 = [
+ 0.5139500,
+ 12.0108556517,
+ 14914.4523349355,
+ -6.3524240E-05,
+ 6.3330532E-08,
+ -2.5428962E-10,
+ 0.3824500,
+ 9.6553010794,
+ 6585.7609102104,
+ -2.1583699E-04,
+ -1.8708058E-07,
+ 9.3204945E-10,
+ 0.3265400,
+ 3.9694765808,
+ 7700.3894694766,
+ 1.5497663E-04,
+ 2.4979472E-07,
+ -1.1318993E-09,
+ 0.2639600,
+ 0.7416325637,
+ 8956.9933799736,
+ 1.4964887E-04,
+ 2.5102751E-07,
+ -1.2407788E-09,
+ 0.1230200,
+ -1.6139220085,
+ 628.3019552485,
+ -2.6638815E-06,
+ 6.1639211E-10,
+ -5.4439728E-11,
+ 0.0775400,
+ 8.7830116346,
+ 16171.0562454324,
+ -6.8852003E-05,
+ 6.4563317E-08,
+ -3.6316908E-10,
+ 0.0606800,
+ 6.4274570623,
+ 7842.3648207073,
+ -2.2116475E-04,
+ -1.8584780E-07,
+ 8.2317000E-10,
+ 0.0497000,
+ 12.0539813334,
+ 14286.1503796870,
+ -6.0860358E-05,
+ 6.2714140E-08,
+ -1.9984990E-10
+ ];
+ static final List M1n = [
+ 3.81034392032, 8.39968473021E+03, -3.31919929753E-05, //月球平黄经系数
+ 3.20170955005E-08, -1.53637455544E-10
+ ];
+
+ static double EnnT = 0; // 调用Enn前先设置EnnT时间变量
+
+ /**
+ * 计算E10,E11,E20等,即:某一组周期项或泊松项算出,计算前先设置EnnT时间
+ *
+ * @param F F
+ * @return 计算E10, E11, E20等
+ */
+ static double Enn(List F) {
+ double v = 0;
+ for (int i = 0; i < F.length; i += 3)
+ v += F[i] * cos(F[i + 1] + EnnT * F[i + 2]);
+ return v;
+ }
+
+ /**
+ * 返回地球位置,日心Date黄道分点坐标
+ *
+ * @param jd jd
+ * @return 返回地球位置, 日心Date黄道分点坐标
+ */
+ static List earCal(double jd) {
+ EnnT = jd / 365250;
+ List llr = new List(3);
+ double t1 = EnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1, t5 = t4 * t1;
+ llr[0] = Enn(E10) +
+ Enn(E11) * t1 +
+ Enn(E12) * t2 +
+ Enn(E13) * t3 +
+ Enn(E14) * t4 +
+ Enn(E15) * t5;
+ llr[1] = Enn(E20) + Enn(E21) * t1;
+ llr[2] = Enn(E30) + Enn(E31) * t1 + Enn(E32) * t2 + Enn(E33) * t3;
+ llr[0] = rad2mrad(llr[0]);
+ return llr;
+ }
+
+// ==================月位置计算===================
+ static double MnnT = 0; // 调用Mnn前先设置MnnT时间变量
+
+ /**
+ * 计算M10,M11,M20等,计算前先设置MnnT时间
+ *
+ * @param F F
+ * @return 计算M10, M11, M20等, 计算前先设置MnnT时间
+ */
+ static double Mnn(List F) {
+ double v = 0, t1 = MnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1;
+ for (int i = 0; i < F.length; i += 6)
+ v += F[i] *
+ sin(F[i + 1] +
+ t1 * F[i + 2] +
+ t2 * F[i + 3] +
+ t3 * F[i + 4] +
+ t4 * F[i + 5]);
+ return v;
+ }
+
+ /**
+ * 返回月球位置,返回地心Date黄道坐标
+ *
+ * @param julian 儒略历
+ * @return return 地心黄道坐标
+ */
+ static List moonCoord(double julian) {
+ MnnT = julian / 36525;
+ double t1 = MnnT, t2 = t1 * t1, t3 = t2 * t1, t4 = t3 * t1;
+ List llr = new List(3);
+ llr[0] = (Mnn(M10) + Mnn(M11) * t1 + Mnn(M12) * t2) / SECOND_PER_RAD;
+ llr[1] = (Mnn(M20) + Mnn(M21) * t1) / SECOND_PER_RAD;
+ llr[2] = (Mnn(M30) + Mnn(M31) * t1) * 0.999999949827;
+ llr[0] =
+ llr[0] + M1n[0] + M1n[1] * t1 + M1n[2] * t2 + M1n[3] * t3 + M1n[4] * t4;
+ llr[0] = rad2mrad(llr[0]); // 地心Date黄道原点坐标(不含岁差)
+ precession(julian, llr); // 补岁差
+ return llr;
+ }
+
+ /**
+ * 地心坐标中的日月位置计算
+ *
+ * @param lx lx=1时计算t时刻日月角距与jiao的差, lx=0计算t时刻太阳黄经与jiao的差
+ * @param time time
+ * @param angle angle
+ * @return 地心坐标中的日月位置计算
+ */
+ static double angleDiff(int lx, double time, double angle) {
+ List sun = earCal(time); // 计算太阳真位置(先算出日心坐标中地球的位置)
+ sun[0] += pi;
+ sun[1] = -sun[1]; // 转为地心坐标
+ addGxc(time, sun); // 补周年光行差
+ if (lx == 0) {
+ Nutation d = nutation(time);
+ sun[0] += d.Lon; // 补黄经章动
+ return rad2mrad(angle - sun[0]);
+ }
+ List moon = moonCoord(time); // 日月角差与章动无关
+ return rad2mrad(angle - (moon[0] - sun[0]));
+ }
+
+ /**
+ * 已知位置反求时间,对于节气计算,应满足t在t1到t1+360天之间,对于Y年第n个节气(n=0是春分),t1可取值Y*365.2422+n*15.2,
+ * 对于朔望计算,应满足t在t1到t1+25天之间,在此范围之外,求右边的根
+ *
+ * @param t1 J2000起算儒略日数,传入的t1是指定角度对应真时刻t的前一些天
+ * @param angle 已知角度(jiao)求时间(t)
+ * @param lx lx=0是太阳黄经达某角度的时刻计算(用于节气计算)
+ * lx=1是日月角距达某角度的时刻计算(用于定朔望等)
+ * @return 已知位置反求时间
+ */
+ static double getTimeFromAngle(double t1, double angle, int lx) {
+ double t2 = t1, t = 0, v;
+ if (lx == 0)
+ t2 += 360; // 在t1到t2范围内求解(范气360天范围),结果置于t
+ else
+ t2 += 25;
+ angle *= pi / 180; // 待搜索目标角
+// 利用截弦法计算
+ double v1 = angleDiff(lx, t1, angle); // v1,v2为t1,t2时对应的黄经
+ double v2 = angleDiff(lx, t2, angle);
+ if (v1 < v2) v2 -= 2 * pi; // 减2pi作用是将周期性角度转为连续角度
+ double k = 1, k2; // k是截弦的斜率
+ for (int i = 0; i < 10; i++) {
+ // 快速截弦求根,通常截弦三四次就已达所需精度
+ k2 = (v2 - v1) / (t2 - t1); // 算出斜率
+ if (Math.abs(k2) > 1e-15) k = k2; // 差商可能为零,应排除
+ t = t1 - v1 / k;
+ v = angleDiff(lx, t, angle); // 直线逼近法求根(直线方程的根)
+ if (v > 1) v -= 2 * pi; // 一次逼近后,v1就已接近0,如果很大,则应减1周
+ if (Math.abs(v) < 1e-8) break; // 已达精度
+ t1 = t2;
+ v1 = v2;
+ t2 = t;
+ v2 = v; // 下一次截弦
+ }
+ return t;
+ }
+
+ /**
+ * 获得某一年24节气
+ *
+ * @param year 年
+ * @return 24节气
+ */
+
+ static List getSolarTerms(int year) {
+ List solarTerms = new List(24);
+ List preOffset = getSolarTermsPreOffset(year - 1);
+ List nextOffset = getSolarTermsNextOffset(year - 1);
+// print("getSolarTerms:" + preOffset.toString());
+// print("getSolarTerms:" + nextOffset.toString());
+ System.arraycopy(preOffset, 0, solarTerms, 0, preOffset.length);
+ System.arraycopy(nextOffset, 0, solarTerms, 22, nextOffset.length);
+
+ double jd = 365.2422 * (year - 2000), q;
+ for (int i = 0; i < 19; i++) {
+ q = getTimeFromAngle(jd + i * 15.2, i * 15.toDouble(), 0);
+ q = q + J2000 + 8 / 24; // 计算第i个节气(i=0是春分),结果转为北京时
+ Time time = setFromJulian(q, true);
+ solarTerms[i + 3] = time.toString() + SOLAR_TERMS[i];
+ }
+
+ return solarTerms;
+ }
+
+ /**
+ * 要获得2018年24节气需要传入2017年
+ *
+ * @param year 要获得2018年24节气需要传入2017年
+ * @return 返回 立春 雨水 惊蛰
+ */
+ static List getSolarTermsPreOffset(int year) {
+ List solarTerms = new List(3);
+ double jd = 365.2422 * (year - 2000), q;
+ for (int i = 21; i < 24; i++) {
+ q = getTimeFromAngle(jd + i * 15.2, i * 15.toDouble(), 0);
+ q = q + J2000 + 8 / 24; // 计算第i个节气(i=0是春分)
+ Time time = setFromJulian(q, true);
+ solarTerms[i - 21] = time.toString() + SOLAR_TERMS[i];
+ }
+ return solarTerms;
+ }
+
+ /**
+ * 要获得2018年24节气需要传入2017年
+ *
+ * @param year 要获得2018年24节气需要传入2017年
+ * @return 返回 小寒大寒
+ */
+ static List getSolarTermsNextOffset(int year) {
+ List solarTerms = new List(2);
+ double jd = 365.2422 * (year - 2000), q;
+ for (int i = 19; i < 21; i++) {
+ q = getTimeFromAngle(jd + i * 15.2, i * 15.toDouble(), 0);
+ q = q + J2000 + 8 / 24; // 计算第i个节气(i=0是春分)
+ Time time = setFromJulian(q, true);
+ solarTerms[i - 19] = time.toString() + SOLAR_TERMS[i];
+ }
+ return solarTerms;
+ }
+}
+
+/**
+ * 章动
+ */
+class Nutation {
+ /**
+ * 章动角
+ */
+ double Lon;
+
+ /**
+ * 交角
+ */
+ double Obl;
+}
+
+class Time {
+ double year;
+ double month;
+ double day;
+ double hour;
+ double minute;
+ double second;
+
+ String toString() {
+ return doubleToString(year) + doubleToString(month) + doubleToString(day);
+ }
+
+ static String doubleToString(double value) {
+ int v = value.toInt();
+ return value < 10 ? "0$v" : v.toString();
+ }
+}
diff --git a/flutter_custom_calendar/lib/week_view.dart b/flutter_custom_calendar/lib/week_view.dart
new file mode 100644
index 0000000..3ce0cf8
--- /dev/null
+++ b/flutter_custom_calendar/lib/week_view.dart
@@ -0,0 +1,31 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_custom_calendar/utils/date_util.dart';
+
+/**
+ * 周视图,只显示本周的日子
+ */
+class WeekView extends StatefulWidget {
+ @override
+ _WeekViewState createState() => _WeekViewState();
+}
+
+class _WeekViewState extends State {
+ @override
+ Widget build(BuildContext context) {
+// DateTime dateTime = DateTime.now();
+//
+// print(dateTime);
+//
+// print(dateTime.subtract(Duration(days: 1)));
+//
+// var berlinWallFell = new DateTime(1989, DateTime.november, 9);
+// var dDay = new DateTime(1944, DateTime.june, 6);
+// Duration difference = berlinWallFell.difference(dDay);
+// print(difference.inDays);
+
+ print(DateUtil.initCalendarForMonthView(
+ 2019, 12, DateTime.now(), DateTime.sunday));
+
+ return Container();
+ }
+}
diff --git a/flutter_custom_calendar/pubspec.lock b/flutter_custom_calendar/pubspec.lock
new file mode 100644
index 0000000..10f7aaa
--- /dev/null
+++ b/flutter_custom_calendar/pubspec.lock
@@ -0,0 +1,139 @@
+# Generated by pub
+# See https://www.dartlang.org/tools/pub/glossary#lockfile
+packages:
+ async:
+ dependency: transitive
+ description:
+ name: async
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.1.0"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.0.4"
+ charcode:
+ dependency: transitive
+ description:
+ name: charcode
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.2"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.14.11"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.12.5"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.6"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.6.2"
+ pedantic:
+ dependency: transitive
+ description:
+ name: pedantic
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.5.0"
+ quiver:
+ dependency: transitive
+ description:
+ name: quiver
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.0.2"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.5.5"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.9.3"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.0.0"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.0.4"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.0"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "0.2.4"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "1.1.6"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ url: "https://pub.flutter-io.cn"
+ source: hosted
+ version: "2.0.8"
+sdks:
+ dart: ">=2.2.0 <3.0.0"
diff --git a/flutter_custom_calendar/pubspec.yaml b/flutter_custom_calendar/pubspec.yaml
new file mode 100644
index 0000000..d6db212
--- /dev/null
+++ b/flutter_custom_calendar/pubspec.yaml
@@ -0,0 +1,53 @@
+name: flutter_custom_calendar
+description: A new Flutter Calendar package.
+version: 0.0.1
+author: xiaodong<450468291@qq.com>
+homepage: https://github.com/LXD312569496/flutter_custom_calendar
+
+environment:
+ sdk: ">=2.1.0 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ flutter_test:
+ sdk: flutter
+
+# For information on the generic Dart part of this file, see the
+# following page: https://www.dartlang.org/tools/pub/pubspec
+
+# The following section is specific to Flutter.
+flutter:
+
+ # To add assets to your package, add an assets section, like this:
+ # assets:
+ # - images/a_dot_burr.jpeg
+ # - images/a_dot_ham.jpeg
+ #
+ # For details regarding assets in packages, see
+ # https://flutter.dev/assets-and-images/#from-packages
+ #
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware.
+
+ # To add custom fonts to your package, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts in packages, see
+ # https://flutter.dev/custom-fonts/#from-packages
diff --git a/flutter_custom_calendar/test/flutter_custom_calendar_test.dart b/flutter_custom_calendar/test/flutter_custom_calendar_test.dart
new file mode 100644
index 0000000..2cd4246
--- /dev/null
+++ b/flutter_custom_calendar/test/flutter_custom_calendar_test.dart
@@ -0,0 +1,13 @@
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
+
+void main() {
+ test('adds one to input values', () {
+ final calculator = Calculator();
+ expect(calculator.addOne(2), 3);
+ expect(calculator.addOne(-7), -6);
+ expect(calculator.addOne(0), 1);
+ expect(() => calculator.addOne(null), throwsNoSuchMethodError);
+ });
+}