publish pub

develop
xiaodong 5 years ago
parent f2425b83b0
commit 99283787b2

@ -0,0 +1,10 @@
.DS_Store
.dart_tool/
.packages
.pub/
build/
ios/.generated/
ios/Flutter/Generated.xcconfig
ios/Runner/GeneratedPluginRegistrant.*

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

@ -0,0 +1,172 @@
<component name="libraryTable">
<library name="Dart Packages" type="DartPackagesLibraryType">
<properties>
<option name="packageNameToDirsMap">
<entry key="async">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/async-2.1.0/lib" />
</list>
</value>
</entry>
<entry key="boolean_selector">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/boolean_selector-1.0.4/lib" />
</list>
</value>
</entry>
<entry key="charcode">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/charcode-1.1.2/lib" />
</list>
</value>
</entry>
<entry key="collection">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/collection-1.14.11/lib" />
</list>
</value>
</entry>
<entry key="flutter">
<value>
<list>
<option value="$PROJECT_DIR$/../../../FlutterSDK/flutter/packages/flutter/lib" />
</list>
</value>
</entry>
<entry key="flutter_test">
<value>
<list>
<option value="$PROJECT_DIR$/../../../FlutterSDK/flutter/packages/flutter_test/lib" />
</list>
</value>
</entry>
<entry key="matcher">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/matcher-0.12.5/lib" />
</list>
</value>
</entry>
<entry key="meta">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/meta-1.1.6/lib" />
</list>
</value>
</entry>
<entry key="path">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/path-1.6.2/lib" />
</list>
</value>
</entry>
<entry key="pedantic">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/pedantic-1.5.0/lib" />
</list>
</value>
</entry>
<entry key="quiver">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.2/lib" />
</list>
</value>
</entry>
<entry key="sky_engine">
<value>
<list>
<option value="$PROJECT_DIR$/../../../FlutterSDK/flutter/bin/cache/pkg/sky_engine/lib" />
</list>
</value>
</entry>
<entry key="source_span">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/source_span-1.5.5/lib" />
</list>
</value>
</entry>
<entry key="stack_trace">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/stack_trace-1.9.3/lib" />
</list>
</value>
</entry>
<entry key="stream_channel">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/stream_channel-2.0.0/lib" />
</list>
</value>
</entry>
<entry key="string_scanner">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/string_scanner-1.0.4/lib" />
</list>
</value>
</entry>
<entry key="term_glyph">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/term_glyph-1.1.0/lib" />
</list>
</value>
</entry>
<entry key="test_api">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/test_api-0.2.4/lib" />
</list>
</value>
</entry>
<entry key="typed_data">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/typed_data-1.1.6/lib" />
</list>
</value>
</entry>
<entry key="vector_math">
<value>
<list>
<option value="$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/vector_math-2.0.8/lib" />
</list>
</value>
</entry>
</option>
</properties>
<CLASSES>
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/async-2.1.0/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/boolean_selector-1.0.4/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/charcode-1.1.2/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/collection-1.14.11/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/matcher-0.12.5/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/meta-1.1.6/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/path-1.6.2/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/pedantic-1.5.0/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/quiver-2.0.2/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/source_span-1.5.5/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/stack_trace-1.9.3/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/stream_channel-2.0.0/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/string_scanner-1.0.4/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/term_glyph-1.1.0/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/test_api-0.2.4/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/typed_data-1.1.6/lib" />
<root url="file://$USER_HOME$/.pub-cache/hosted/pub.flutter-io.cn/vector_math-2.0.8/lib" />
<root url="file://$PROJECT_DIR$/../../../FlutterSDK/flutter/bin/cache/pkg/sky_engine/lib" />
<root url="file://$PROJECT_DIR$/../../../FlutterSDK/flutter/packages/flutter/lib" />
<root url="file://$PROJECT_DIR$/../../../FlutterSDK/flutter/packages/flutter_test/lib" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -0,0 +1,19 @@
<component name="libraryTable">
<library name="Dart SDK">
<CLASSES>
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/async" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/collection" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/convert" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/core" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/developer" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/html" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/io" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/isolate" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/math" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/mirrors" />
<root url="file:///Users/linxiaodong/Flutter/FlutterSDK/flutter/bin/cache/dart-sdk/lib/typed_data" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

@ -0,0 +1,7 @@
<component name="libraryTable">
<library name="Flutter Plugins" type="FlutterPluginsLibraryType">
<CLASSES />
<JAVADOC />
<SOURCES />
</library>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectType">
<option name="id" value="io.flutter" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/flutter_custom_calendar.iml" filepath="$PROJECT_DIR$/flutter_custom_calendar.iml" />
</modules>
</component>
</project>

@ -0,0 +1,295 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="067adf6d-3e64-4468-95c5-20dd90a656ce" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/lib/base_day_view.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/base_week_bar.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/calendar_view.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/constants/constants.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/controller.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/default_combine_day_view.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/default_custom_day_view.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/default_week_bar.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/demo_page/custom_style_page.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/demo_page/default_style_page.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/demo_page/main.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/demo_page/multi_select_style_page.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/demo_page/progress_style_page.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/flutter_calendar.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/model/date_model.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/month_view.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/month_view_pager.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/style/style.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/utils/date_util.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/utils/lunar_util.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/utils/math_util.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/utils/solar_term_util.dart" afterDir="false" />
<change afterPath="$PROJECT_DIR$/lib/week_view.dart" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.dart_tool/" />
<ignored path="$PROJECT_DIR$/.idea/" />
<ignored path="$PROJECT_DIR$/.pub/" />
<ignored path="$PROJECT_DIR$/build/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/flutter_custom_calendar.dart">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/base_day_view.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="34">
<caret line="2" column="39" selection-start-line="2" selection-start-column="39" selection-end-line="2" selection-end-column="39" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/constants/constants.dart">
<provider selected="true" editor-type-id="text-editor" />
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/demo_page/custom_style_page.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" selection-start-line="6" selection-end-line="6" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/base_week_bar.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="1" selection-start-line="1" selection-end-line="1" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/lib/default_week_bar.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="51">
<caret line="3" selection-start-line="3" selection-end-line="3" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="10" column="42" selection-start-line="10" selection-start-column="42" selection-end-line="10" selection-end-column="42" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="41" selection-start-line="4" selection-start-column="41" selection-end-line="4" selection-end-column="41" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>flutter_calendar</find>
</findStrings>
<replaceStrings>
<replace>flutter_custom_calendar</replace>
</replaceStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/lib/base_day_view.dart" />
<option value="$PROJECT_DIR$/lib/demo_page/custom_style_page.dart" />
<option value="$PROJECT_DIR$/lib/base_week_bar.dart" />
<option value="$PROJECT_DIR$/lib/default_week_bar.dart" />
<option value="$PROJECT_DIR$/CHANGELOG.md" />
<option value="$PROJECT_DIR$/pubspec.yaml" />
</list>
</option>
</component>
<component name="ProjectFrameBounds">
<option name="x" value="720" />
<option name="y" value="23" />
<option name="width" value="720" />
<option name="height" value="806" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator currentView="ProjectPane" proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="flutter_custom_calendar" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_custom_calendar" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_custom_calendar" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_custom_calendar" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_custom_calendar" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_custom_calendar" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="constants" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="flutter_custom_calendar" type="b2602c69:ProjectViewProjectNode" />
<item name="flutter_custom_calendar" type="462c0819:PsiDirectoryNode" />
<item name="lib" type="462c0819:PsiDirectoryNode" />
<item name="demo_page" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
<pane id="PackagesPane" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="dart.analysis.tool.window.force.activate" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="show.migrate.to.gradle.popup" value="false" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/lib/demo_page" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/lib" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="067adf6d-3e64-4468-95c5-20dd90a656ce" name="Default Changelist" comment="" />
<created>1558196651106</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1558196651106</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="720" y="23" width="720" height="806" extended-state="0" />
<editor active="true" />
<layout>
<window_info id="Structure" side_tool="true" />
<window_info id="Image Layers" />
<window_info id="Designer" />
<window_info id="Resources Explorer" />
<window_info id="Capture Tool" />
<window_info id="Favorites" side_tool="true" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.25516224" />
<window_info anchor="bottom" id="Dart Analysis" visible="true" weight="0.32913166" />
<window_info anchor="bottom" id="Version Control" />
<window_info anchor="bottom" id="TODO" />
<window_info anchor="bottom" id="Run" />
<window_info anchor="bottom" id="Debug" />
<window_info anchor="bottom" id="Terminal" />
<window_info anchor="bottom" id="Event Log" side_tool="true" />
<window_info anchor="bottom" id="Flutter Performance" side_tool="true" />
<window_info anchor="bottom" id="Find" />
<window_info anchor="right" id="Capture Analysis" />
<window_info anchor="right" id="Theme Preview" />
<window_info anchor="right" id="Flutter Inspector" />
<window_info anchor="right" id="Flutter Outline" />
<window_info anchor="right" id="Palette&#9;" />
</layout>
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/lib/flutter_custom_calendar.dart">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/lib/base_day_view.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="34">
<caret line="2" column="39" selection-start-line="2" selection-start-column="39" selection-end-line="2" selection-end-column="39" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/constants/constants.dart">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://$PROJECT_DIR$/lib/demo_page/custom_style_page.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="102">
<caret line="6" selection-start-line="6" selection-end-line="6" />
<folding>
<element signature="e#0#39#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/base_week_bar.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="17">
<caret line="1" selection-start-line="1" selection-end-line="1" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/lib/default_week_bar.dart">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="51">
<caret line="3" selection-start-line="3" selection-end-line="3" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/CHANGELOG.md">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="170">
<caret line="10" column="42" selection-start-line="10" selection-start-column="42" selection-end-line="10" selection-end-column="42" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/pubspec.yaml">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="68">
<caret line="4" column="41" selection-start-line="4" selection-start-column="41" selection-end-line="4" selection-end-column="41" />
</state>
</provider>
</entry>
</component>
</project>

@ -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

@ -0,0 +1,11 @@
## [0.0.1] - 2019/5/19.
## 主要功能
* 支持公历,农历,节气,传统节日,常用节假日
* 日期范围设置默认支持的最大日期范围为1971.01-2055.12
* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
* 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。
* 跳转到指定日期,默认支持动画切换
* 自定义日历Item支持组合widget的方式和利用canvas绘制的方式
* 自定义顶部的WeekBar
* 可以给Item添加自定义的额外数据实现各种额外的功能。比如实现进度条风格的日历

@ -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.

@ -0,0 +1,245 @@
FlutterCalendarWidget
Flutter上的一个日历控件可以定制成自己想要的样子。
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb76a959b93b3?w=828&h=1792&f=jpeg&s=92910">
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb793e4dbd2f2?w=828&h=1792&f=jpeg&s=102231">
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb79f153ab321?w=828&h=1792&f=jpeg&s=1288910">
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb7a35d41361c?w=828&h=1792&f=jpeg&s=10674210">
## 主要功能
* 支持公历,农历,节气,传统节日,常用节假日
* 日期范围设置默认支持的最大日期范围为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_SELECTMODE_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<DateModel> selectedDateList = new Set(); //被选中的日期,用于多选
DateModel selectDateModel; //当前选择项,用于单选
int maxMultiSelectCount; //多选,最多选多少个
Map<DateTime, Object> 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<DateModel> 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
* 支持周视图
* 支持动画切换周视图和月视图

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/lib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.dart_tool" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
<excludeFolder url="file://$MODULE_DIR$/.pub" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content>
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart Packages" level="project" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>

@ -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';
/**
* canvasitem
*/
abstract class BaseCustomDayWidget extends StatelessWidget {
DateModel dateModel;
BaseCustomDayWidget(
this.dateModel,
);
@override
Widget build(BuildContext context) {
return Container(
child: new CustomPaint(
painter:
//isSelecteditem
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;
}
}
/**
* widgetitem
*/
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);
}

@ -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<Widget> getWeekDayWidget() {
return List.generate(7, (index) {
return getChild(index);
});
}
Widget getChild(int index) {
return new Expanded(
child: getWeekBarItem(index),
);
}
}

@ -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<CalendarViewWidget> {
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: <Widget>[
/**
* constsetStateview
*/
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,
),
),
],
),
);
}
}

@ -0,0 +1,73 @@
class Constants {
//
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2;
/**
*
*/
static const List<String> WEEK_LIST = [
"周一",
"周二",
"周三",
"周四",
"周五",
"周六",
"周日"
];
/**
*
*/
static const List<String> LUNAR_MONTH_TEXT = [
"春节",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"冬月",
"腊月",
];
/**
*
*/
static const List<String> LUNAR_DAY_TEXT = [
"初一",
"初二",
"初三",
"初四",
"初五",
"初六",
"初七",
"初八",
"初九",
"初十",
"十一",
"十二",
"十三",
"十四",
"十五",
"十六",
"十七",
"十八",
"十九",
"二十",
"廿一",
"廿二",
"廿三",
"廿四",
"廿五",
"廿六",
"廿七",
"廿八",
"廿九",
"三十"
];
}

@ -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<DateTime> EMPTY_SET = {};
static const Map<DateTime, Object> EMPTY_MAP = {};
//,MODE_SINGLE_SELECTMODE_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<DateModel> selectedDateList = new Set(); //,
DateModel selectDateModel; //,
int maxMultiSelectCount; //
Map<DateTime, Object> extraDataMap = new Map(); //
//
OnMonthChange monthChange; //
OnCalendarSelect calendarSelect; //
OnMultiSelectOutOfRange multiSelectOutOfRange; //
OnMultiSelectOutOfSize multiSelectOutOfSize; //
//
DayWidgetBuilder dayWidgetBuilder; //item
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //weekbar
/**
*
*/
List<DateModel> 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<DateTime> selectedDateTimeList = EMPTY_SET,
DateModel selectDateModel,
int maxMultiSelectCount = 9999,
Map<DateTime, Object> 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<DateModel> getMultiSelectCalendar() {
if (selectedDateList.isEmpty) {
return null;
}
return selectedDateList;
}
//
DateModel getSingleSelectCalendar() {
if (selectDateModel == null) {
return null;
}
return selectDateModel;
}
}
/**
* weekBar
*/
Widget defaultWeekBarWidget() {
return DefaultWeekBar();
}
/**
* 使canvasitem
*/
Widget defaultCustomDayWidget(DateModel dateModel) {
return DefaultCustomDayWidget(
dateModel,
);
}
/**
* 使widgetitem
*/
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();

@ -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';
/**
* widgetitem
*/
//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: <Widget>[
// new Column(
// mainAxisSize: MainAxisSize.max,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: <Widget>[
// //
// 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: <Widget>[
new Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//
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: <Widget>[
new Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
//
new Expanded(
child: Center(
child: new Text(
dateModel.day.toString(),
style: currentMonthTextStyle,
),
),
),
//
new Expanded(
child: Center(
child: new Text(
"${dateModel.lunarString}",
style: lunarTextStyle,
),
),
),
],
)
],
),
);
}
}

@ -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';
/**
* StatelessWidgetstate
*/
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));
}

@ -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<Widget> 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,
),
);
}
}

@ -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<CustomStylePage> {
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: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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<String> 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));
}
}

@ -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<DefaultStylePage> {
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: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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.
);
}
}

@ -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: <String, WidgetBuilder>{
"/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: <Widget>[
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("进度条风格+单选"),
),
],
),
),
);
}
}

@ -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<MultiSelectStylePage> {
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: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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<String> 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));
}
}

@ -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<ProgressStylePage> {
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<DateTime, int> 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: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
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<String> 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));
}
}

@ -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';

@ -0,0 +1,7 @@
library flutter_custom_calendar;
/// A Calculator.
class Calculator {
/// Returns [value] plus 1.
int addOne(int value) => value + 1;
}

@ -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:truefalse
@override
String toString() {
return 'DateModel{year: $year, month: $month, day: $day}';
} //
//DateTime
DateTime getDateTime() {
return new DateTime(year, month, day);
}
//DateTimemodel
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;
}

@ -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<DateModel> selectedDateList; //
DateModel selectDateModel; //,
DayWidgetBuilder dayWidgetBuilder;
OnMultiSelectOutOfRange multiSelectOutOfRange; //
OnMultiSelectOutOfSize multiSelectOutOfSize; //
int year;
int month;
int day;
DateModel minSelectDate;
DateModel maxSelectDate;
int selectMode;
int maxMultiSelectCount;
Map<DateTime, Object> 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<MonthView> {
List<DateModel> 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),
);
});
}
}

@ -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<DateModel> selectedDateList; //,
DateModel selectDateModel; //,
final List<DateModel> monthList;
PageController pageController;
DateModel minSelectDate;
DateModel maxSelectDate;
int selectMode;
int maxMultiSelectCount;
Map<DateTime, Object> 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<MonthViewPager> {
@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),
// );
}
}

@ -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);

@ -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<DateModel> initCalendarForMonthView(
int year, int month, DateTime currentDate, int weekStart,
{DateModel minSelectDate,
DateModel maxSelectDate,
Map<DateTime, Object> extraDataMap}) {
weekStart = DateTime.monday;
//
int mPreDiff = getIndexOfFirstDayInMonth(new DateTime(year, month));
//
int monthDayCount = getMonthDaysCount(year, month);
print("$year$month月,有$monthDayCount天,第一天的index为${mPreDiff}");
List<DateModel> 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;
}
}

File diff suppressed because it is too large Load Diff

@ -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<String> src, int srcPos, List<String> dest,
int destPos, int length) {
List.copyRange(dest, destPos, src, srcPos, srcPos+length);
}
}

File diff suppressed because it is too large Load Diff

@ -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<WeekView> {
@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();
}
}

@ -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"

@ -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

@ -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);
});
}
Loading…
Cancel
Save