Merge pull request #50 from fluttercandies/master

修改24节气,初始化问题
develop
LXD312569496 5 years ago committed by GitHub
commit a56c7b57de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

335
API.md

@ -0,0 +1,335 @@
## 主要Api文档
- [主要Api文档](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3)
- [配置日历的UI](#%e9%85%8d%e7%bd%ae%e6%97%a5%e5%8e%86%e7%9a%84ui)
- [参数说明](#%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e)
- [配置Controller](#%e9%85%8d%e7%bd%aecontroller)
- [通用参数说明](#%e9%80%9a%e7%94%a8%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e)
- [给controller添加事件监听](#%e7%bb%99controller%e6%b7%bb%e5%8a%a0%e4%ba%8b%e4%bb%b6%e7%9b%91%e5%90%ac)
- [利用controller来控制日历的切换支持配置动画](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e6%8e%a7%e5%88%b6%e6%97%a5%e5%8e%86%e7%9a%84%e5%88%87%e6%8d%a2%e6%94%af%e6%8c%81%e9%85%8d%e7%bd%ae%e5%8a%a8%e7%94%bb)
- [利用controller来获取当前日历的状态和数据](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e8%8e%b7%e5%8f%96%e5%bd%93%e5%89%8d%e6%97%a5%e5%8e%86%e7%9a%84%e7%8a%b6%e6%80%81%e5%92%8c%e6%95%b0%e6%8d%ae)
- [如何自定义UI](#%e5%a6%82%e4%bd%95%e8%87%aa%e5%ae%9a%e4%b9%89ui)
- [自定义WeekBar](#%e8%87%aa%e5%ae%9a%e4%b9%89weekbar)
- [自定义日历Item](#%e8%87%aa%e5%ae%9a%e4%b9%89%e6%97%a5%e5%8e%86item)
- [根据实际场景自定义额外的数据extraData](#%e6%a0%b9%e6%8d%ae%e5%ae%9e%e9%99%85%e5%9c%ba%e6%99%af%e8%87%aa%e5%ae%9a%e4%b9%89%e9%a2%9d%e5%a4%96%e7%9a%84%e6%95%b0%e6%8d%aeextradata)
- [实现进度条样式的日历](#%e5%ae%9e%e7%8e%b0%e8%bf%9b%e5%ba%a6%e6%9d%a1%e6%a0%b7%e5%bc%8f%e7%9a%84%e6%97%a5%e5%8e%86)
- [实现自定义各种标记的日历](#%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%ae%9a%e4%b9%89%e5%90%84%e7%a7%8d%e6%a0%87%e8%ae%b0%e7%9a%84%e6%97%a5%e5%8e%86)
- [手动修改自定义的数据](#%e6%89%8b%e5%8a%a8%e4%bf%ae%e6%94%b9%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9a%84%e6%95%b0%e6%8d%ae)
- [DateModel实体类](#datemodel%e5%ae%9e%e4%bd%93%e7%b1%bb)
### 配置日历的UI
日历UI相关的配置是在CalendarViewWidget的构造函数里面进行配置就行了。
```
CalendarViewWidget(
{Key key,
this.dayWidgetBuilder = defaultCustomDayWidget,
this.weekBarItemWidgetBuilder = defaultWeekBarWidget,
@required this.calendarController,
this.boxDecoration,
this.padding = EdgeInsets.zero,
this.margin = EdgeInsets.zero,
this.verticalSpacing = 10,
this.itemSize})
: super(key: key);
```
#### 参数说明
| 属性 | 含义 | 默认值 |
| :----------------------: | :------------------------: | :--------------------------------------: |
| weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 |
| dayWidgetBuilder | 创建日历item | 默认样式 |
| verticalSpacing | 日历item之间的竖直方向间距 | 默认10 |
| boxDecoration | 整体的背景设置 | 默认为空 |
| itemSize | 每个item的边长 | 手机默认是屏幕宽度/7网页默认屏幕高度/7 |
| padding | 日历的padding | 默认为EdgeInsets.zero |
| margin | 日历的padding | 默认为EdgeInsets.zero |
### 配置Controller
两个作用:
一个是显示日历所需要的相关数据是在controller里面进行配置的。
一个是可以利用controller添加事件监听使用controller进行操作日历
```
//构造函数
CalendarController(
{int selectMode = CalendarConstants.MODE_SINGLE_SELECT,
int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH,
int minYear = 1971,
int maxYear = 2055,
int minYearMonth = 1,
int maxYearMonth = 12,
int nowYear,
int nowMonth,
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<DateModel, Object> extraDataMap = EMPTY_MAP})
```
#### 通用参数说明
| 属性 | 含义 | 默认值 |
| :-----------------: | :-----------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| selectMode | 选择模式,表示单选或者多选 | 默认是单选<br>static const int MODE_SINGLE_SELECT = 1;<br>static const int MODE_MULTI_SELECT = 2; |
| showMode | 展示模式 | 默认是只展示月视图<br>static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图<br>static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图<br>static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图<br>static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 |
| minYear | 日历显示的最小年份 | 1971 |
| maxYear | 日历显示的最大年份 | 2055 |
| minYearMonth | 日历显示的最小年份的月份 | 1 |
| maxYearMonth | 日历显示的最大年份的月份 | 12 |
| nowYear | 日历显示的当前的年份 | -1 |
| nowMonth | 日历显示的当前的月份 | -1 |
| minSelectYear | 可以选择的最小年份 | 1971 |
| minSelectMonth | 可以选择的最小年份的月份 | 1 |
| minSelectDay | 可以选择的最小月份的日子 | 1 |
| maxSelectYear | 可以选择的最大年份 | 2055 |
| maxSelectMonth | 可以选择的最大年份的月份 | 12 |
| maxSelectDay | 可以选择的最大月份的日子 | 30注意不能超过对应月份的总天数 |
| selectedDateList | 被选中的日期,用于多选 | 默认为空Set, Set<DateModel> selectedDateList = new Set() |
| selectDateModel | 当前选择项,用于单选 | 默认为空 |
| maxMultiSelectCount | 多选,最多选多少个 | hhh |
| extraDataMap | 自定义额外的数据 | 默认为空MapMap<DateTime, Object> extraDataMap = new Map() |
#### 给controller添加事件监听
| 方法 | 含义 | 默认值 |
| :-----------------------------------------------------------------------: | :--------------------: | :----: |
| void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 |
| void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 |
| void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 |
| void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 |
| void addExpandChangeListener(ValueChanged<bool> expandChange) | 监听日历的展开收缩状态 |
#### 利用controller来控制日历的切换支持配置动画
| 方法 | 含义 | 默认值 |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----: |
| Future<bool> previousPage() | 滑动到上一个页面会自动根据当前的展开状态滑动到上一个月或者上一个星期。如果已经在第一个页面没有上一个页面就会返回false其他情况返回true |
| Future<bool> nextPage() | 滑动到下一个页面会自动根据当前的展开状态滑动到下一个月或者下一个星期。如果已经在最后一个页面没有下一个页面就会返回false其他情况返回true |
| 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() | 切换到上一个月份 |
| void toggleExpandStatus() | 切换展开状态 |
| void changeExtraData(Map<DateModel, Object> newMap) | 修改自定义的额外数据并刷新日历 |
#### 利用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,
),
);
}
}
```
第二种做法你也可以直接重写build方法进行更加的自定义绘制。
```
class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"];
//可以直接重写build方法weekbar底部添加下划线
@override
Widget build(BuildContext context) {
List<Widget> children = List();
var items = getWeekDayWidget();
children.add(Row(
children: items,
));
children.add(Divider(
color: Colors.grey,
));
return Column(
children: children,
);
}
@override
Widget getWeekBarItem(int index) {
return new Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: new Center(
child: new Text(
weekList[index],
style:
TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)),
),
),
);
}
}
```
#### 自定义日历Item
提供两种方法一种是利用组合widget的方式来创建一种是利用Canvas来自定义绘制Item。最后只需要在CalendarController的构造参数中进行配置就可以了。
* 利用组合widget的方式来创建继承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
}
}
```
* 利用Canvas来自定义绘制继承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);
}
}
```
### 根据实际场景自定义额外的数据extraData
#### 实现进度条样式的日历
我们可以自定义每个item的进度条数据保存到map中最后赋值给controller的extraDataMap。
```
//外部处理每个dateModel所对应的进度
Map<DateModel, int> progressMap = {
DateModel.fromDateTime(temp.add(Duration(days: 1))): 0,
DateModel.fromDateTime(temp.add(Duration(days: 2))): 20,
DateModel.fromDateTime(temp.add(Duration(days: 3))): 40,
DateModel.fromDateTime(temp.add(Duration(days: 4))): 60,
DateModel.fromDateTime(temp.add(Duration(days: 5))): 80,
DateModel.fromDateTime(temp.add(Duration(days: 6))): 100,
};
//创建CalendarController对象的时候将extraDataMap赋值就行了
new CalendarController(
extraDataMap: progressMap)
//绘制DayWidget的时候可以直接从dateModel的extraData对象中拿到想要的数据
int progress = dateModel.extraData;
```
#### 实现自定义各种标记的日历
```
//外部处理每个dateModel所对应的标记
Map<DateModel, String> customExtraData = {
DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班",
};
//创建CalendarController对象的时候将extraDataMap赋值就行了
new CalendarController(
extraDataMap: customExtraData)
//绘制DayWidget的时候可以直接从dateModel的extraData对象中拿到想要的数据
String data = dateModel.extraData;
```
#### 手动修改自定义的数据
当自定义的数据发生变化的时候可以使用controller的changeExtraData(Map<DateModel, Object> newMap)方法,
日历会自动刷新,根据新的额外数据进行绘制。
```
//可以动态修改extraDataMap
void changeExtraData(Map<DateModel, Object> newMap) {
this.calendarConfiguration.extraDataMap = newMap;
this.calendarProvider.generation.value++;
}
```
### DateModel实体类
日历所用的日期的实体类DateModel有下面这些属性。可以在自定义绘制DayWidget的时候根据相应的属性进行判断后绘制相应的UI。
| 属性 | 含义 | 类型 | 默认值 |
| :---------------: | :---------------------------------------------------: | :----: | :------: |
| year | 年份 | int |
| month | 月份 | int |
| day | 日期 | int | 默认为1 |
| lunarYear | 农历年份 | int |
| lunarMonth | 农历月份 | int |
| lunarDay | 农历日期 | int |
| lunarString | 农历字符串 | String |
| solarTerm | 24节气 | String |
| gregorianFestival | gregorianFestival | String |
| traditionFestival | 传统农历节日 | String |
| isCurrentDay | 是否是今天 | bool | false |
| isLeapYear | 是否是闰年 | bool | false |
| isWeekend | 是否是周末 | bool | false |
| isInRange | 是否在范围内,比如可以实现在某个范围外,设置置灰的功能 | bool | false |
| isSelected | 是否被选中,用来实现一些标记或者选择功能 | bool | false |
| extraData | 自定义的额外数据 | Object | 默认为空 |
| isCurrentMonth | 是否是当前月份 | bool |
| 方法 | 含义 |
| :---------------------------------------: | :-------------------------------------------------------: |
| DateTime getDateTime() | 将DateModel转化成DateTime |
| DateModel fromDateTime(DateTime dateTime) | 根据DateTime创建对应的model并初始化农历和传统节日等信息 |
| bool operator ==(Object other) | 重写==方法可以判断两个dateModel是否是同一天 |

@ -0,0 +1,339 @@
## Main API documents
- [Main API documents](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3)
- [Configure calendar UI](#%e9%85%8d%e7%bd%ae%e6%97%a5%e5%8e%86%e7%9a%84ui)
- [Parameter description](#%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e)
- [Configure controller](#%e9%85%8d%e7%bd%aecontroller)
- [Parameter description](#%e9%80%9a%e7%94%a8%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e)
- [Add event listening to controller](#%e7%bb%99controller%e6%b7%bb%e5%8a%a0%e4%ba%8b%e4%bb%b6%e7%9b%91%e5%90%ac)
- [Using controller to control the switching of calendar and support the configuration of animation](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e6%8e%a7%e5%88%b6%e6%97%a5%e5%8e%86%e7%9a%84%e5%88%87%e6%8d%a2%e6%94%af%e6%8c%81%e9%85%8d%e7%bd%ae%e5%8a%a8%e7%94%bb)
- [Using controller to get the status and data of current calendar](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e8%8e%b7%e5%8f%96%e5%bd%93%e5%89%8d%e6%97%a5%e5%8e%86%e7%9a%84%e7%8a%b6%e6%80%81%e5%92%8c%e6%95%b0%e6%8d%ae)
- [How to customize UI](#%e5%a6%82%e4%bd%95%e8%87%aa%e5%ae%9a%e4%b9%89ui)
- [Customize weekbar](#%e8%87%aa%e5%ae%9a%e4%b9%89weekbar)
- [Custom calendar item](#%e8%87%aa%e5%ae%9a%e4%b9%89%e6%97%a5%e5%8e%86item)
- [Customize extra data extradata according to the actual scenario](#%e6%a0%b9%e6%8d%ae%e5%ae%9e%e9%99%85%e5%9c%ba%e6%99%af%e8%87%aa%e5%ae%9a%e4%b9%89%e9%a2%9d%e5%a4%96%e7%9a%84%e6%95%b0%e6%8d%aeextradata)
- [Calendar with progress bar style](#%e5%ae%9e%e7%8e%b0%e8%bf%9b%e5%ba%a6%e6%9d%a1%e6%a0%b7%e5%bc%8f%e7%9a%84%e6%97%a5%e5%8e%86)
- [Implement custom calendars for various tags](#%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%ae%9a%e4%b9%89%e5%90%84%e7%a7%8d%e6%a0%87%e8%ae%b0%e7%9a%84%e6%97%a5%e5%8e%86)
- [Modify customized data manually](#%e6%89%8b%e5%8a%a8%e4%bf%ae%e6%94%b9%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9a%84%e6%95%b0%e6%8d%ae)
- [DateModel Entry](#datemodel%e5%ae%9e%e4%bd%93%e7%b1%bb)
### Configure calendar UI
The configuration of calendar UI is done in the constructor of calendarviewwidget.
```
CalendarViewWidget(
{Key key,
this.dayWidgetBuilder = defaultCustomDayWidget,
this.weekBarItemWidgetBuilder = defaultWeekBarWidget,
@required this.calendarController,
this.boxDecoration,
this.padding = EdgeInsets.zero,
this.margin = EdgeInsets.zero,
this.verticalSpacing = 10,
this.itemSize})
: super(key: key);
```
#### Parameter description
| Attribute | Meaning | Default value |
| :----------------------: | :------------------------: | :--------------------------------------: |
| weekBarItemWidgetBuilder | Create the weekbar at the top | Default style |
| dayWidgetBuilder | Create calendar item | Default style |
| verticalSpacing | Vertical spacing between calendar items | Default is 10 |
| boxDecoration | calendar background setting | Default is null |
| itemSize | Size of each item | The default screen width of mobile phone / 7, and the default screen height of web page / 7 |
| padding | Calendar padding | EdgeInsets.zero |
| margin | Calendar padding | EdgeInsets.zero |
### Configure controller
Two action
One is to display the related data required by the calendar, which is configured in the controller.
One is to use the controller to add event monitoring and use the controller to operate the calendar.
```
//构造函数
CalendarController(
{int selectMode = CalendarConstants.MODE_SINGLE_SELECT,
int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH,
int minYear = 1971,
int maxYear = 2055,
int minYearMonth = 1,
int maxYearMonth = 12,
int nowYear,
int nowMonth,
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<DateModel, Object> extraDataMap = EMPTY_MAP})
```
#### General parameter description
| Attribute | Meaning | Default value |
| :-----------------: | :-----------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
| selectMode | Selection mode, indicating single selection or multiple selection | default is single select<br>static const int MODE_SINGLE_SELECT = 1;<br>static const int MODE_MULTI_SELECT = 2; |
| showMode | Display mode | 默认是只展示月视图<br>static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图<br>static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图<br>static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图<br>static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 |
| minYear | Minimum year for calendar display | 1971 |
| maxYear | Maximum year displayed in calendar | 2055 |
| minYearMonth | The month of the smallest year displayed by the calendar | 1 |
| maxYearMonth | The month of the largest year displayed by the calendar | 12 |
| nowYear | Current year displayed by calendar | -1 |
| nowMonth | Current month displayed by calendar | -1 |
| minSelectYear | Minimum year that can be selected | 1971 |
| minSelectMonth | Month of the smallest year that can be selected | 1 |
| minSelectDay | The day of the smallest month you can choose | 1 |
| maxSelectYear | Maximum year that can be selected | 2055 |
| maxSelectMonth | Month of the largest year you can choose | 12 |
| maxSelectDay | The day of the largest month you can choose | 30注意不能超过对应月份的总天数 |
| selectedDateList | Selected date for multiple selections | 默认为空Set, Set<DateModel> selectedDateList = new Set() |
| selectDateModel | Current selection, for radio selection | 默认为空 |
| maxMultiSelectCount | Multiple choice, how many at most | hhh |
| extraDataMap | Customize additional data | 默认为空MapMap<DateTime, Object> extraDataMap = new Map() |
#### Add event listening to controller
| Method | Meaning | Default value |
| :-----------------------------------------------------------------------: | :--------------------: | :----: |
| void addMonthChangeListener(OnMonthChange listener) | Month switching event |
| void addOnCalendarSelectListener(OnCalendarSelect listener) | Click to select an event |
| void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | Multiple selection out of the specified range |
| void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | Multiple selection exceeds the limit |
| void addExpandChangeListener(ValueChanged<bool> expandChange) | Monitor the expansion and contraction status of calendar |
#### Using controller to control the switching of calendar and support the configuration of animation
| Method | Meaning | Default value |
| :-------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----: |
| Future<bool> previousPage() | Sliding to the previous page will automatically slide to the previous month or week according to the current deployment status. If it is already on the first page and there is no previous page, it will return false, otherwise it will return true |
| Future<bool> nextPage() | Sliding to the next page will automatically move to the next month or week according to the current deployment status. If it is already on the last page and there is no next page, it will return false, otherwise it will return true |
| void moveToCalendar(int year, int month, int day, {bool needAnimation = false,Duration duration = const Duration(milliseconds: 500),Curve curve = Curves.ease}) | To specified date |
| void moveToNextYear() | Switch to next year |
| void moveToPreviousYear() | Switch to previous year |
| void moveToNextMonth() | Switch to the next month |
| void moveToPreviousMonth() | Switch to previous month |
| void toggleExpandStatus() | Toggle deployment state |
| void changeExtraData(Map<DateModel, Object> newMap) | Modify custom extra data and refresh calendar |
#### Using controller to get the status and data of current calendar
| Method | Meaning | Default Value |
| :-------------------------------------: | :--------------------: | :----: |
| DateTime getCurrentMonth() | Get the current month |
| Set<DateModel> getMultiSelectCalendar() | Get selected date,multiple choices |
| DateModel getSingleSelectCalendar() | Get selected date,single choiice |
### How to customize UI
Including custom weekbar and custom calendar item. Defaultxxwidget is used by default.
As long as we inherit the corresponding base class and implement the corresponding methods, then we only need to implement the corresponding builder methods when configuring the controller.
```
//支持自定义绘制
DayWidgetBuilder dayWidgetBuilder; //create calendar item
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //create weekbar
```
#### Customize weekbar
The first way is to inherit baseweekbar and override getweekbaritem (index) method. Whatever you do, just return a 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,
),
);
}
}
```
In the second way, you can directly rewrite the build method for more custom drawing.
```
class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"];
//可以直接重写build方法weekbar底部添加下划线
@override
Widget build(BuildContext context) {
List<Widget> children = List();
var items = getWeekDayWidget();
children.add(Row(
children: items,
));
children.add(Divider(
color: Colors.grey,
));
return Column(
children: children,
);
}
@override
Widget getWeekBarItem(int index) {
return new Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: new Center(
child: new Text(
weekList[index],
style:
TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)),
),
),
);
}
}
```
#### Custom calendar item
There are two methods, one is to create by combining widgets, and the other is to draw items by using canvas. Finally, you only need to configure in the construction parameters of the calendarcontroller。
* Create by combining widgets: inherit basecombinedaywidget, rewrite getnormalwidget (datemodel datemodel) and getselectedwidget (datemodel datemodel), and return the corresponding widget.
```
class DefaultCombineDayWidget extends BaseCombineDayWidget {
DefaultCombineDayWidget(DateModel dateModel) : super(dateModel);
@override
Widget getNormalWidget(DateModel dateModel) {
//实现默认状态下的UI
}
@override
Widget getSelectedWidget(DateModel dateModel) {
//绘制被选中的UI
}
}
```
* Use canvas to define drawing, inherit basecustomdaywidget, rewrite drawnormal and drawselected, and draw item by yourself.
```
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);
}
}
```
### Customize extra data extradata according to the actual scenario
#### Calendar with progress bar style
We can customize the progress bar data of each item, save it in the map, and finally assign it to the extradatamap of the controller
```
//Externally process the tag corresponding to each datemodel
Map<DateModel, int> progressMap = {
DateModel.fromDateTime(temp.add(Duration(days: 1))): 0,
DateModel.fromDateTime(temp.add(Duration(days: 2))): 20,
DateModel.fromDateTime(temp.add(Duration(days: 3))): 40,
DateModel.fromDateTime(temp.add(Duration(days: 4))): 60,
DateModel.fromDateTime(temp.add(Duration(days: 5))): 80,
DateModel.fromDateTime(temp.add(Duration(days: 6))): 100,
};
//When creating the calendarcontroller object, assign the extradatamap
new CalendarController(
extraDataMap: progressMap)
//When drawing daywidget, you can get the desired data directly from the extradata object of datemodel
int progress = dateModel.extraData;
```
#### Implement custom calendars for various tags
```
//Externally process the tag corresponding to each datemodel
Map<DateModel, String> customExtraData = {
DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班",
};
//When creating the calendarcontroller object, assign the extradatamap
new CalendarController(
extraDataMap: customExtraData)
//When drawing daywidget, you can get the desired data directly from the extradata object of datemodel
String data = dateModel.extraData;
```
#### Modify customized data manually
When the customized data changes, you can use the controller's change extradata (map < datemodel, Object > NewMap) method,The calendar will refresh automatically and draw based on the new additional data
```
//可以动态修改extraDataMap
void changeExtraData(Map<DateModel, Object> newMap) {
this.calendarConfiguration.extraDataMap = newMap;
this.calendarProvider.generation.value++;
}
```
### DateModel Entry
The entity class datemodel of the date used by the calendar has the following properties. You can draw the corresponding UI after judging according to the corresponding properties when you customize the daywidget.
| Attribute | Meaning | Type | Default Value |
| :---------------: | :---------------------------------------------------: | :----: | :------: |
| year | 年份 | int |
| month | 月份 | int |
| day | 日期 | int | 默认为1 |
| lunarYear | 农历年份 | int |
| lunarMonth | 农历月份 | int |
| lunarDay | 农历日期 | int |
| lunarString | 农历字符串 | String |
| solarTerm | 24 solar terms | String |
| gregorianFestival | gregorianFestival | String |
| traditionFestival | 传统农历节日 | String |
| isCurrentDay | 是否是今天 | bool | false |
| isLeapYear | 是否是闰年 | bool | false |
| isWeekend | 是否是周末 | bool | false |
| isInRange | Whether it is in the range, for example, it can set the gray function outside a range | bool | false |
| isSelected | Is it selected to implement some marking or selection functions | bool | false |
| extraData | Custom extra data | Object | 默认为空 |
| isCurrentMonth | 是否是当前月份 | bool |
| Method | Meaning |
| :---------------------------------------: | :-------------------------------------------------------: |
| DateTime getDateTime() | Convert datemodel to datetime |
| DateModel fromDateTime(DateTime dateTime) | Create corresponding model according to datetime, and initialize information such as lunar calendar and traditional festivals |
| bool operator ==(Object other) | Override the = = method to determine whether two datemodels are the same day |

@ -1,14 +1,21 @@
## [1.0.0] - 2019/9/22 ### 近期修改
* 重构日历的代码
### [2.0.0] - 2019/11/01
* 日历支持padding和margin属性item的大小计算修改
* 实现日历整体自适应高度
* controller提供changeExtraDataMap的方法可以随时动态的修改自定义数据extraDataMap
* 支持显示月视图和周视图的情况优先显示周视图MODE_SHOW_WEEK_AND_MONTH
* 支持verticalSpacing和itemSize属性
### [1.0.0] - 2019/10/10
* 重构日历的代码,进行性能优化
* 创建configuration类将配置的信息放到这里 * 创建configuration类将配置的信息放到这里
* 引入provider状态管理,避免深层嵌套传递信息 * 引入provider状态管理,避免深层嵌套传递信息
* 实现周视图,并实现周视图和月视图之间的联动 * 实现周视图,并实现周视图和月视图之间的联动
* DateModel增加isCurrentMonth用于绘制月视图可以屏蔽一些非当前月份的日子前面几天或者后面几天的isCurrentMonth是为false的。 * DateModel增加isCurrentMonth用于绘制月视图可以屏蔽一些非当前月份的日子前面几天或者后面几天的isCurrentMonth是为false的。
### [0.0.1] - 2019/5/19.
## [0.0.1] - 2019/5/19.
## 主要功能
* 支持公历,农历,节气,传统节日,常用节假日 * 支持公历,农历,节气,传统节日,常用节假日
* 日期范围设置默认支持的最大日期范围为1971.01-2055.12 * 日期范围设置默认支持的最大日期范围为1971.01-2055.12
* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰 * 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰

@ -1,12 +1,21 @@
FlutterCalendarWidget
## FlutterCalendarWidget
Flutter上的一个日历控件可以定制成自己想要的样子。 Flutter上的一个日历控件可以定制成自己想要的样子。
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb76a959b93b3?w=828&h=1792&f=jpeg&s=92910" width="300" height="620"><img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb793e4dbd2f2?w=828&h=1792&f=jpeg&s=102231" width="300" height="620"> Language: [English](README_en.md)|中文简体
<img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb79f153ab321?w=828&h=1792&f=jpeg&s=1288910" width="300" height="620"><img src="https://user-gold-cdn.xitu.io/2019/5/18/16acb7a35d41361c?w=828&h=1792&f=jpeg&s=10674210" width="300" height="620">
- [FlutterCalendarWidget](#fluttercalendarwidget)
- [概述](#%e6%a6%82%e8%bf%b0)
- [在线Demo](#%e5%9c%a8%e7%ba%bfdemo)
- [效果图](#%e6%95%88%e6%9e%9c%e5%9b%be)
- [使用](#%e4%bd%bf%e7%94%a8)
- [2.0版本](#20%e7%89%88%e6%9c%ac)
- [注意事项](#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9)
- [主要API文档](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3)
### 概述
## 主要功能
* 支持公历,农历,节气,传统节日,常用节假日 * 支持公历,农历,节气,传统节日,常用节假日
* 日期范围设置默认支持的最大日期范围为1971.01-2055.12 * 日期范围设置默认支持的最大日期范围为1971.01-2055.12
* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰 * 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
@ -15,304 +24,115 @@ Flutter上的一个日历控件可以定制成自己想要的样子。
* 自定义日历Item支持组合widget的方式和利用canvas绘制的方式 * 自定义日历Item支持组合widget的方式和利用canvas绘制的方式
* 自定义顶部的WeekBar * 自定义顶部的WeekBar
* 根据实际场景可以给Item添加自定义的额外数据实现各种额外的功能。比如实现进度条风格的日历实现日历的各种标记 * 根据实际场景可以给Item添加自定义的额外数据实现各种额外的功能。比如实现进度条风格的日历实现日历的各种标记
* 支持周视图的展示 * 支持周视图的展示,支持月份视图和星期视图的展示与切换联动
* 支持月份视图和星期视图的展示与切换联动
### 在线Demo
日历支持web预览[点击此处进入预览](https://lxd312569496.github.io/flutter_custom_calendar/#/)
### 效果图
<table>
<tbody>
<tr>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hjt66daxj30n01dsad5.jpg" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db060ca77ecad2?w=828&h=1792&f=png&s=126261" width="280" height="620">
</td>
</tr>
<tr>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db061203661eca?w=828&h=1792&f=png&s=157230" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db0614e44b6e0d?w=828&h=1792&f=png&s=145423" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db0619af4c854a?w=828&h=1792&f=png&s=129203" width="280" height="620">
</td>
</tr>
<tr>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db061ef0ed35dd?w=828&h=1792&f=png&s=81260" width="280" height="620">
</td>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hji5yiqkj30u01sx0wy.jpg" width="280" height="620">
</td>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hjntithzj30u01sxtcl.jpg" width="280" height="620">
</td>
</tr>
</tbody>
</table>
## 近期修改
### [1.0.0] - 2019/10/10
* 重构日历的代码,进行性能优化
* 创建configuration类将配置的信息放到这里
* 引入provider状态管理,避免深层嵌套传递信息
* 实现周视图,并实现周视图和月视图之间的联动
* DateModel增加isCurrentMonth用于绘制月视图可以屏蔽一些非当前月份的日子前面几天或者后面几天的isCurrentMonth是为false的。
### [0.0.1] - 2019/5/19.
* 支持公历,农历,节气,传统节日,常用节假日
* 日期范围设置默认支持的最大日期范围为1971.01-2055.12
* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
* 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。
* 跳转到指定日期,默认支持动画切换
* 自定义日历Item支持组合widget的方式和利用canvas绘制的方式
* 自定义顶部的WeekBar
* 可以给Item添加自定义的额外数据实现各种额外的功能。比如实现进度条风格的日历
## 使用 ## 使用
在pubspec.yaml添加依赖: 1.在pubspec.yaml文件里面添加依赖:
``` ```
flutter_custom_calendar: flutter_custom_calendar:
git: git:
url: https://github.com/LXD312569496/flutter_custom_calendar.git url: https://github.com/LXD312569496/flutter_custom_calendar.git
``` ```
引入flutter_custom_calendar,就可以使用CalendarViewWidget配置CalendarController就可以了。
```
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
CalendarViewWidget({@required this.calendarController, this.boxDecoration});
```
* boxDecoration用来配置整体的背景
* 利用CalendarController来配置一些数据并且可以通过CalendarController进行一些操作或者事件监听比如滚动到下一个月获取当前被选中的Item等等。
## 配置CalendarController
下面是CalendarController中一些支持自定义配置的属性。不配置的话会有对应的默认值。
个人觉得配置的含义主要包括了3个方面的配置。
* 一个是显示日历所需要的相关数据,
* 一个是显示日历的自定义UI的相关配置
* 一个是对日历的监听事件进行配置。
2.导入flutter_custom_calendar库
``` ```
//构造函数 import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
CalendarController(
{int selectMode = Constants.MODE_SINGLE_SELECT,
int showMode = Constants.MODE_SHOW_ONLY_MONTH,
bool expandStatus = true,
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,
double verticalSpacing = 10,
bool enableExpand = true,
Map<DateModel, Object> extraDataMap = EMPTY_MAP})
``` ```
### 数据方面的配置 3.创建CalendarViewWidget对象配置CalendarController
属性 | 含义 | 默认值
:-: | :-: | :-:
selectMode | 选择模式,表示单选或者多选 | 默认是单选<br>static const int MODE_SINGLE_SELECT = 1;<br>static const int MODE_MULTI_SELECT = 2;
showMode|展示模式| 默认是只展示月视图<br>static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图<br>static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图<br>static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持月和星期视图切换
minYear | 日历显示的最小年份| 1971
maxYear | 日历显示的最大年份| 2055
minYearMonth | 日历显示的最小年份的月份| 1
maxYearMonth | 日历显示的最大年份的月份| 12
nowYear | 日历显示的当前的年份| -1
nowMonth | 日历显示的当前的月份| -1
minSelectYear | 可以选择的最小年份| 1971
minSelectMonth | 可以选择的最小年份的月份| 1
minSelectDay | 可以选择的最小月份的日子| 1
maxSelectYear | 可以选择的最大年份| 2055
maxSelectMonth | 可以选择的最大年份的月份| 12
maxSelectDay | 可以选择的最大月份的日子| 30注意不能超过对应月份的总天数
selectedDateList | 被选中的日期,用于多选| 默认为空Set, Set<DateModel> selectedDateList = new Set()
selectDateModel | 当前选择项,用于单选| 默认为空
maxMultiSelectCount | 多选,最多选多少个| hhh
extraDataMap | 自定义额外的数据| 默认为空MapMap<DateTime, Object> extraDataMap = new Map()
### UI绘制相关的配置
属性 | 含义 | 默认值
:-: | :-: | :-:
weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式
dayWidgetBuilder | 创建日历item | 默认样式
verticalSpacing|日历item之间的竖直方向间距|默认10
boxDecoration |整体的背景设置|
itemSize| 每个item的边长|默认是屏幕宽度/7|
### 事件监听的配置
方法 | 含义 | 默认值
:-: | :-: | :-:
void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 |
void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 |
void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 |
void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 |
void addExpandChangeListener(ValueChanged<bool> expandChange)|监听日历的展开收缩状态|
## 利用controller来控制日历的切换支持配置动画
方法 | 含义 | 默认值
:-: | :-: | :-:
Future<bool> previousPage()|滑动到上一个页面会自动根据当前的展开状态滑动到上一个月或者上一个星期。如果已经在第一个页面没有上一个页面就会返回false其他情况返回true|
Future<bool> nextPage()|滑动到下一个页面会自动根据当前的展开状态滑动到下一个月或者下一个星期。如果已经在最后一个页面没有下一个页面就会返回false其他情况返回true|
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()|切换到上一个月份|
void toggleExpandStatus()|切换展开状态|
## 利用controller来获取日历的一些数据信息
方法 | 含义 | 默认值
:-: | :-: | :-:
DateTime getCurrentMonth()|获取当前的月份|
Set<DateModel> getMultiSelectCalendar()|获取被选中的日期,多选|
DateModel getSingleSelectCalendar()|获取被选中的日期,单选|
## 如何自定义UI
包括自定义WeekBar、自定义日历Item默认使用的都是DefaultXXXWidget。
只要继承对应的Base类实现相应的方法然后只需要在配置Controller的时候实现相应的Builder方法就可以了。
``` ```
//支持自定义绘制 CalendarController controller= new CalendarController(
DayWidgetBuilder dayWidgetBuilder; //创建日历item minYear: 2018,
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar minYearMonth: 1,
``` maxYear: 2020,
### 自定义WeekBar maxYearMonth: 12,
继承BaseWeekBar重写getWeekBarItem(index)方法就可以。随便你怎么实现只需要返回一个Widget就可以了。 showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK);
``` CalendarViewWidget calendar= CalendarViewWidget(
class DefaultWeekBar extends BaseWeekBar { calendarController: controller,
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。 * boxDecoration用来配置整体的背景
* 利用CalendarController来配置一些数据并且可以通过CalendarController进行一些操作或者事件监听比如滚动到下一个月获取当前被选中的Item等等。
4.操作日历
``` ```
class DefaultCustomDayWidget extends BaseCustomDayWidget { controller.toggleExpandStatus();//月视图和周视图的切换
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);
}
}
``` ```
### 根据实际场景自定义额外的数据extraData
#### 自定义每个item的进度条数据
``` ```
//外部处理每个dateModel所对应的进度 controller.previousPage();//操作日历切换到上一页
Map<DateModel, int> progressMap = {
DateModel.fromDateTime(temp.add(Duration(days: 1))): 0,
DateModel.fromDateTime(temp.add(Duration(days: 2))): 20,
DateModel.fromDateTime(temp.add(Duration(days: 3))): 40,
DateModel.fromDateTime(temp.add(Duration(days: 4))): 60,
DateModel.fromDateTime(temp.add(Duration(days: 5))): 80,
DateModel.fromDateTime(temp.add(Duration(days: 6))): 100,
};
//创建CalendarController对象的时候将extraDataMap赋值就行了
new CalendarController(
extraDataMap: progressMap)
//绘制DayWidget的时候可以直接从dateModel的extraData对象中拿到想要的数据
int progress = dateModel.extraData;
``` ```
#### 自定义各种标记
``` ```
//外部处理每个dateModel所对应的标记 controller.nextPage();//操作日历切换到下一页
Map<DateModel, String> customExtraData = {
DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事",
DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班",
};
//创建CalendarController对象的时候将extraDataMap赋值就行了
new CalendarController(
extraDataMap: customExtraData)
//绘制DayWidget的时候可以直接从dateModel的extraData对象中拿到想要的数据
String data = dateModel.extraData;
``` ```
## 2.0版本
主要改动:
* UI配置相关的参数移动到CalendarView的构造方法里面旧版本是在controller里面配置
* 日历支持padding和margin属性item的大小计算修改
* 实现日历整体自适应高度
* controller提供changeExtraDataMap的方法可以随时动态的修改自定义数据extraDataMap
* 支持显示月视图和周视图的情况优先显示周视图MODE_SHOW_WEEK_AND_MONTH
* 支持verticalSpacing和itemSize属性
## DateModel实体类
日历所用的日期的实体类DateModel有下面这些属性。可以在自定义绘制DayWidget的时候根据相应的属性进行判断后绘制相应的UI。
属性|含义|类型|默认值
:-: | :-: | :-: |:-:
year|年份|int|
month|月份|int|
day|日期|int|默认为1
lunarYear|农历年份|int|
lunarMonth|农历月份|int|
lunarDay|农历日期|int|
lunarString|农历字符串|String|
solarTerm|24节气|String|
gregorianFestival|gregorianFestival|String|
traditionFestival|传统农历节日|String|
isCurrentDay|是否是今天|bool|false
isLeapYear|是否是闰年|bool|false
isWeekend|是否是周末|bool|false
isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false
isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false
extraData|自定义的额外数据|Object|默认为空
## 注意事项
方法|含义| * 如果使用2.0之前的版本则需要将UI配置相关的参数移动到CalendarView的构造方法里面旧版本是在controller里面配置
:-: | :-: | * 暂时没有发现其他问题,如果有其他问题,可以跟我说一下。
DateTime getDateTime()|将DateModel转化成DateTime * 如果你用这个库做了日历,可以将展示结果分享给我,我贴到文档上进行展示
DateModel fromDateTime(DateTime dateTime)|根据DateTime创建对应的model并初始化农历和传统节日等信息
bool operator ==(Object other)|重写==方法可以判断两个dateModel是否是同一天
## 主要API文档
[API Documentation](API.md)
## TODO LIST
* 优化代码实现
* 继续写几个不同风格的Demo
* 支持手势操作
* 实现高度自适应

@ -0,0 +1,140 @@
## FlutterCalendarWidget
A calendar widget in flutter,you can design what you want to show!
Language:English|[中文简体](README.md)
- [FlutterCalendarWidget](#fluttercalendarwidget)
- [Overview](#overview)
- [Online Demo](#online-demo)
- [Example](#example)
- [Getting Started](#getting-started)
- [2.0 version](#20-version)
- [matters needing attention](#matters-needing-attention)
- [API Documentation](#api-documentation)
### Overview
* Support the Gregorian calendar, lunar calendar, solar terms, traditional festivals and common holidays
* Date range setting, the maximum date range supported by default is 1971.01-2055.12
* Disable date range settings. For example, you can click within a range of dates and gray the dates outside the range
* Support single selection and multiple selection modes, and provide multiple selection of callbacks exceeding the limit and multiple selection of callbacks exceeding the specified range.
* Jump to the specified date. Animation switching is supported by default
* Custom Calendar items, support the way of combining widgets and drawing with canvas
* Customize the weekbar at the top
* According to the actual scene, you can add custom additional data to the item to realize various additional functions. For example, to realize the calendar of progress bar style and various marks of calendar
* Support weekly view display, monthly view and weekly view display and switching linkage
### Online Demo
Calendar supports web Preview[Click here for preview](https://lxd312569496.github.io/flutter_custom_calendar/#/)
### Example
<table>
<tbody>
<tr>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hjt66daxj30n01dsad5.jpg" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db060ca77ecad2?w=828&h=1792&f=png&s=126261" width="280" height="620">
</td>
</tr>
<tr>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db061203661eca?w=828&h=1792&f=png&s=157230" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db0614e44b6e0d?w=828&h=1792&f=png&s=145423" width="280" height="620">
</td>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db0619af4c854a?w=828&h=1792&f=png&s=129203" width="280" height="620">
</td>
</tr>
<tr>
<td>
<img src="https://user-gold-cdn.xitu.io/2019/10/9/16db061ef0ed35dd?w=828&h=1792&f=png&s=81260" width="280" height="620">
</td>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hji5yiqkj30u01sx0wy.jpg" width="280" height="620">
</td>
<td>
<img src="https://tva1.sinaimg.cn/large/006y8mN6ly1g8hjntithzj30u01sxtcl.jpg" width="280" height="620">
</td>
</tr>
</tbody>
</table>
## Getting Started
1.add dependencies into you project pubspec.yaml file:
```
flutter_custom_calendar:
git:
url: https://github.com/LXD312569496/flutter_custom_calendar.git
```
2.import flutter_custom_calendar lib
```
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
```
3.create CalendarViewWidget objectprofile CalendarController
```
CalendarController controller= new CalendarController(
minYear: 2018,
minYearMonth: 1,
maxYear: 2020,
maxYearMonth: 12,
showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK);
CalendarViewWidget calendar= CalendarViewWidget(
calendarController: controller,
),
```
4.operate controller
```
controller.toggleExpandStatus();//Switch between month view and week view
```
```
controller.previousPage();//Action calendar switch to previous page
```
```
controller.nextPage();//Action calendar switch to next page
```
## 2.0 version
Major changes
* The UI configuration related parameters are moved to the calendar view construction method (the old version is configured in the controller)
* Calendar supports padding and margin attributes, and item size calculation and modification.
* Realize the overall adaptive height of calendar
* The controller provides the method of changing extradatamap, which can dynamically modify the customized data extradatamap at any time.
* It supports the display of monthly view and weekly view, with weekly view as the priority, and mode "show" week "and" month "
* Supports verticalspacing and itemsize properties
## matters needing attention
* If you use the version before 2.0, you need to move the UI configuration related parameters to the calendar view construction method (the old version is configured in the controller).
* I haven't found any other problems for the time being. If you have any, please let me know.
* If you use this library to make a calendar, you can share the display results with me, and I will paste them on the document for display.
## API Documentation
[API Documentation](API.md)

63
example/.gitignore vendored

@ -1,41 +1,36 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store .DS_Store
.dart_tool/ .atom/
.buildlog/
.packages .history
.pub/
.idea/
.vagrant/
.sconsign.dblite
.svn/ .svn/
*.swp # IntelliJ related
profile *.iml
*.ipr
DerivedData/ *.iws
.idea/
.generated/
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata # The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
*.moved-aside # Flutter/Dart/Pub related
**/doc/api/
.dart_tool/
.flutter-plugins
.packages
.pub-cache/
.pub/
/build/
*.pyc # Web related
*sync/ lib/generated_plugin_registrant.dart
Icon?
.tags*
build/ # Exceptions to above rules.
.android/ !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
.ios/
.flutter-plugins

@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited. # This file should be version controlled and should not be manually edited.
version: version:
revision: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b revision: 0120c414fbc5d11c503e2091f420c02ffd6dda67
channel: beta channel: master
project_type: module project_type: app

@ -1,8 +1,16 @@
# example # example1
A new Flutter module. A new Flutter project.
## Getting Started ## Getting Started
For help getting started with Flutter, view our online This project is a starting point for a Flutter application.
[documentation](https://flutter.dev/).
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.

@ -0,0 +1,7 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

@ -0,0 +1,67 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example1"
minSdkVersion 16
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example1">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

@ -0,0 +1,32 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example1">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="example1"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>

@ -0,0 +1,12 @@
package com.example.example1
import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
GeneratedPluginRegistrant.registerWith(this)
}
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
</resources>

@ -0,0 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example1">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

@ -0,0 +1,31 @@
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
android.useAndroidX=true
android.enableJetifier=true

@ -0,0 +1,6 @@
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip

@ -0,0 +1,15 @@
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}

@ -1,17 +0,0 @@
<?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="sourceFolder" forTests="false" />
<orderEntry type="library" name="Dart SDK" level="project" />
<orderEntry type="library" name="Flutter Plugins" level="project" />
</component>
</module>

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="android" name="Android">
<configuration>
<option name="ALLOW_USER_CONFIGURATION" value="false" />
<option name="GEN_FOLDER_RELATIVE_PATH_APT" value="/.android/gen" />
<option name="GEN_FOLDER_RELATIVE_PATH_AIDL" value="/.android/gen" />
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/.android/AndroidManifest.xml" />
<option name="RES_FOLDER_RELATIVE_PATH" value="/.android/res" />
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/.android/assets" />
<option name="LIBS_FOLDER_RELATIVE_PATH" value="/.android/libs" />
<option name="PROGUARD_LOGS_FOLDER_RELATIVE_PATH" value="/.android/proguard_logs" />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/.android">
<sourceFolder url="file://$MODULE_DIR$/.android/Flutter/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/.android/gen" isTestSource="false" generated="true" />
</content>
<orderEntry type="jdk" jdkName="Android API 25 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Flutter for Android" level="project" />
</component>
</module>

@ -0,0 +1,32 @@
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>

@ -0,0 +1 @@
#include "Generated.xcconfig"

@ -0,0 +1 @@
#include "Generated.xcconfig"

@ -0,0 +1,518 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,
3B80C3941E831B6300D905FE /* App.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
3B80C3931E831B6300D905FE /* App.framework */,
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEBA1CF902C7004384FC /* Flutter.framework */,
9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */,
);
name = Flutter;
sourceTree = "<group>";
};
97C146E51CF9000F007C117D = {
isa = PBXGroup;
children = (
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
);
sourceTree = "<group>";
};
97C146EF1CF9000F007C117D /* Products */ = {
isa = PBXGroup;
children = (
97C146EE1CF9000F007C117D /* Runner.app */,
);
name = Products;
sourceTree = "<group>";
};
97C146F01CF9000F007C117D /* Runner */ = {
isa = PBXGroup;
children = (
97C146FA1CF9000F007C117D /* Main.storyboard */,
97C146FD1CF9000F007C117D /* Assets.xcassets */,
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
97C147021CF9000F007C117D /* Info.plist */,
97C146F11CF9000F007C117D /* Supporting Files */,
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
);
path = Runner;
sourceTree = "<group>";
};
97C146F11CF9000F007C117D /* Supporting Files */ = {
isa = PBXGroup;
children = (
);
name = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
);
buildRules = (
);
dependencies = (
);
name = Runner;
productName = Runner;
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "The Chromium Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
CreatedOnToolsVersion = 7.3.1;
LastSwiftMigration = 1100;
};
};
};
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 97C146E51CF9000F007C117D;
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
97C146ED1CF9000F007C117D /* Runner */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
97C146EC1CF9000F007C117D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Thin Binary";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin";
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Run Script";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
97C146EA1CF9000F007C117D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C146FB1CF9000F007C117D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
97C147001CF9000F007C117D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
249021D3217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Profile;
};
249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example1;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Profile;
};
97C147031CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
97C147041CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
97C147061CF9000F007C117D /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example1;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
97C147071CF9000F007C117D /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
ENABLE_BITCODE = NO;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Flutter",
);
PRODUCT_BUNDLE_IDENTIFIER = com.example.example1;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147031CF9000F007C117D /* Debug */,
97C147041CF9000F007C117D /* Release */,
249021D3217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
isa = XCConfigurationList;
buildConfigurations = (
97C147061CF9000F007C117D /* Debug */,
97C147071CF9000F007C117D /* Release */,
249021D4217E4FDB00AE95B9 /* Profile */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 97C146E61CF9000F007C117D /* Project object */;
}

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Profile"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>

@ -0,0 +1,13 @@
import UIKit
import Flutter
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}

@ -0,0 +1,122 @@
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "Icon-App-1024x1024@1x.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "LaunchImage.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "LaunchImage@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

@ -0,0 +1,5 @@
# Launch Screen Assets
You can customize the launch screen with your own desired assets by replacing the image files in this directory.
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
</imageView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
</constraints>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
<resources>
<image name="LaunchImage" width="168" height="185"/>
</resources>
</document>

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>example1</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$(FLUTTER_BUILD_NAME)</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>

@ -0,0 +1 @@
#import "GeneratedPluginRegistrant.h"

@ -0,0 +1,253 @@
import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
class BlueStylePage extends StatefulWidget {
BlueStylePage({Key key, this.title}) : super(key: key);
final String title;
@override
_BlueStylePageState createState() => _BlueStylePageState();
}
class _BlueStylePageState extends State<BlueStylePage> {
ValueNotifier<String> text;
ValueNotifier<String> selectText;
CalendarController controller;
Map<DateModel, String> customExtraData = {};
@override
void initState() {
super.initState();
controller = new CalendarController(
showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK,
extraDataMap: customExtraData);
controller.addMonthChangeListener(
(year, month) {
text.value = "$year$month";
},
);
controller.addOnCalendarSelectListener((dateModel) {
//
selectText.value =
"单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}";
});
text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}");
selectText = new ValueNotifier(
"单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}");
}
@override
Widget build(BuildContext context) {
var calendarWidget = CalendarViewWidget(
weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
},
calendarController: controller,
boxDecoration: BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
color: Colors.white,
),
padding: EdgeInsets.only(left: 20, right: 20, bottom: 10),
margin: const EdgeInsets.only(
left: 15,
right: 15,
),
);
return SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff6219EC),
),
backgroundColor: Color(0xff6219EC),
body: new Container(
child: new Column(
children: <Widget>[
SizedBox(
height: 20,
),
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
height: 100,
margin: const EdgeInsets.only(left: 15, right: 15),
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
color: Colors.white),
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 30),
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: "Februaly",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w700,
fontSize: 30),
),
TextSpan(
text: " 2019",
style: TextStyle(
color: Colors.black, fontSize: 30),
),
],
),
),
),
],
),
),
calendarWidget
],
),
ValueListenableBuilder(
valueListenable: selectText,
builder: (context, value, child) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(selectText.value),
);
}),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
controller.toggleExpandStatus();
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
),
);
}
}
class CustomStyleWeekBarItem extends BaseWeekBar {
final List<String> weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"];
//build
@override
Widget build(BuildContext context) {
List<Widget> children = List();
var items = getWeekDayWidget();
children.add(Row(
children: items,
));
children.add(Divider(
color: Colors.grey,
));
return Column(
children: children,
);
}
@override
Widget getWeekBarItem(int index) {
return new Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: new Center(
child: new Text(
weekList[index],
style:
TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)),
),
),
);
}
}
class CustomStyleDayWidget extends BaseCombineDayWidget {
CustomStyleDayWidget(DateModel dateModel) : super(dateModel);
final TextStyle normalTextStyle =
TextStyle(fontWeight: FontWeight.w700, color: Colors.black);
final TextStyle noIsCurrentMonthTextStyle =
TextStyle(fontWeight: FontWeight.w700, color: Colors.grey);
@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: dateModel.isCurrentMonth
? normalTextStyle
: noIsCurrentMonthTextStyle,
),
),
),
],
),
],
),
);
}
@override
Widget getSelectedWidget(DateModel dateModel) {
return Container(
// margin: EdgeInsets.all(8),
decoration: new BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
color: Color(0xffFED32B),
),
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: dateModel.isCurrentMonth
? normalTextStyle
: noIsCurrentMonthTextStyle,
),
),
),
],
),
],
),
);
}
}

@ -43,13 +43,9 @@ class _CustomSignPageState extends State<CustomSignPage> {
@override @override
void initState() { void initState() {
super.initState();
controller = new CalendarController( controller = new CalendarController(
weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
},
extraDataMap: customExtraData); extraDataMap: customExtraData);
controller.addMonthChangeListener( controller.addMonthChangeListener(
@ -101,6 +97,12 @@ class _CustomSignPageState extends State<CustomSignPage> {
), ),
CalendarViewWidget( CalendarViewWidget(
calendarController: controller, calendarController: controller,
weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
},
), ),
ValueListenableBuilder( ValueListenableBuilder(
valueListenable: selectText, valueListenable: selectText,
@ -113,6 +115,7 @@ class _CustomSignPageState extends State<CustomSignPage> {
floatingActionButton: FloatingActionButton( floatingActionButton: FloatingActionButton(
onPressed: () { onPressed: () {
controller.toggleExpandStatus(); controller.toggleExpandStatus();
// controller.changeExtraData({});
}, },
tooltip: 'Increment', tooltip: 'Increment',
child: Icon(Icons.add), child: Icon(Icons.add),
@ -122,7 +125,7 @@ class _CustomSignPageState extends State<CustomSignPage> {
} }
class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["", "", "", "", "", "", ""]; final List<String> weekList = ["", "", "", "", "", "", ""];
@override @override
Widget getWeekBarItem(int index) { Widget getWeekBarItem(int index) {

@ -21,11 +21,9 @@ class _CustomStylePageState extends State<CustomStylePage> {
@override @override
void initState() { void initState() {
controller = new CalendarController(weekBarItemWidgetBuilder: () { super.initState();
return CustomStyleWeekBarItem(); controller = new CalendarController(
}, dayWidgetBuilder: (dateModel) { selectDateModel: DateModel.fromDateTime(DateTime.now()));
return CustomStyleDayWidget(dateModel);
});
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {
@ -76,7 +74,12 @@ class _CustomStylePageState extends State<CustomStylePage> {
), ),
CalendarViewWidget( CalendarViewWidget(
calendarController: controller, calendarController: controller,
), weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
}),
ValueListenableBuilder( ValueListenableBuilder(
valueListenable: selectText, valueListenable: selectText,
builder: (context, value, child) { builder: (context, value, child) {
@ -95,7 +98,7 @@ class _CustomStylePageState extends State<CustomStylePage> {
} }
class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["", "", "", "", "", "", ""]; final List<String> weekList = ["", "", "", "", "", "", ""];
@override @override
Widget getWeekBarItem(int index) { Widget getWeekBarItem(int index) {

@ -21,13 +21,14 @@ class _DefaultStylePageState extends State<DefaultStylePage> {
@override @override
void initState() { void initState() {
super.initState();
DateTime now = DateTime.now(); DateTime now = DateTime.now();
controller = new CalendarController( controller = new CalendarController(
minYear: now.year, minYear: now.year - 1,
minYearMonth: now.month - 2, minYearMonth: 1,
maxYear: now.year, maxYear: now.year + 1,
maxYearMonth: now.month + 1, maxYearMonth: 12,
showMode: Constants.MODE_SHOW_WEEK_AND_MONTH); showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK);
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {

@ -1,6 +1,7 @@
import 'package:example/only_week_page.dart'; import 'only_week_page.dart';
import 'red_style_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'blue_style_page.dart';
import 'custom_sign_page.dart'; import 'custom_sign_page.dart';
import 'custom_style_page.dart'; import 'custom_style_page.dart';
import 'default_style_page.dart'; import 'default_style_page.dart';
@ -39,6 +40,8 @@ class MyApp extends StatelessWidget {
"/only_week_view": (context) => OnlyWeekPage( "/only_week_view": (context) => OnlyWeekPage(
title: "仅显示周视图", title: "仅显示周视图",
), ),
"/blue_style_page": (context) => BlueStylePage(title: "蓝色背景Demo"),
"/red_style_page": (context) => RedStylePage(title: "蓝色背景Demo"),
}, },
title: 'Flutter Demo', title: 'Flutter Demo',
theme: ThemeData( theme: ThemeData(
@ -91,6 +94,18 @@ class HomePage extends StatelessWidget {
}, },
child: new Text("仅显示周视图"), child: new Text("仅显示周视图"),
), ),
new RaisedButton(
onPressed: () {
Navigator.pushNamed(context, "/blue_style_page");
},
child: new Text("蓝色Demo"),
),
new RaisedButton(
onPressed: () {
Navigator.pushNamed(context, "/red_style_page");
},
child: new Text("红色Demo"),
)
], ],
), ),
), ),

@ -21,18 +21,17 @@ class _MultiSelectStylePageState extends State<MultiSelectStylePage> {
@override @override
void initState() { void initState() {
super.initState();
controller = new CalendarController( controller = new CalendarController(
selectMode: Constants.MODE_MULTI_SELECT, selectMode: CalendarConstants.MODE_MULTI_SELECT,
maxMultiSelectCount: 5, maxMultiSelectCount: 5,
minSelectYear: 2019, minSelectYear: 2019,
minSelectMonth: 5, minSelectMonth: 5,
minSelectDay: 20, minSelectDay: 20,
weekBarItemWidgetBuilder: () { selectedDateTimeList: {
return CustomStyleWeekBarItem(); DateTime.now(),
}, }
dayWidgetBuilder: (dateModel) { );
return CustomStyleDayWidget(dateModel);
});
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {
@ -49,7 +48,7 @@ class _MultiSelectStylePageState extends State<MultiSelectStylePage> {
text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}"); text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}");
selectText = new ValueNotifier( selectText = new ValueNotifier(
"多选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); "多选模式\n选中的时间:\n${controller.getMultiSelectCalendar().join("\n")}");
} }
@override @override
@ -83,7 +82,12 @@ class _MultiSelectStylePageState extends State<MultiSelectStylePage> {
), ),
CalendarViewWidget( CalendarViewWidget(
calendarController: controller, calendarController: controller,
), weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
}),
ValueListenableBuilder( ValueListenableBuilder(
valueListenable: selectText, valueListenable: selectText,
builder: (context, value, child) { builder: (context, value, child) {
@ -102,7 +106,7 @@ class _MultiSelectStylePageState extends State<MultiSelectStylePage> {
} }
class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["", "", "", "", "", "", ""]; final List<String> weekList = ["", "", "", "", "", "", ""];
@override @override
Widget getWeekBarItem(int index) { Widget getWeekBarItem(int index) {
@ -119,7 +123,6 @@ class CustomStyleDayWidget extends BaseCustomDayWidget {
@override @override
void drawNormal(DateModel dateModel, Canvas canvas, Size size) { void drawNormal(DateModel dateModel, Canvas canvas, Size size) {
bool isWeekend = dateModel.isWeekend;
bool isInRange = dateModel.isInRange; bool isInRange = dateModel.isInRange;
// //

@ -21,13 +21,14 @@ class _OnlyWeekPageState extends State<OnlyWeekPage> {
@override @override
void initState() { void initState() {
super.initState();
DateTime now = DateTime.now(); DateTime now = DateTime.now();
controller = new CalendarController( controller = new CalendarController(
minYear: now.year, minYear: now.year,
minYearMonth: now.month - 2, minYearMonth: now.month - 2,
maxYear: now.year, maxYear: now.year,
maxYearMonth: now.month + 1, maxYearMonth: now.month + 1,
showMode: Constants.MODE_SHOW_ONLY_WEEK); showMode: CalendarConstants.MODE_SHOW_ONLY_WEEK);
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {

@ -22,6 +22,7 @@ class _ProgressStylePageState extends State<ProgressStylePage> {
@override @override
void initState() { void initState() {
super.initState();
DateTime now = DateTime.now(); DateTime now = DateTime.now();
DateTime temp = DateTime(now.year, now.month, now.day); DateTime temp = DateTime(now.year, now.month, now.day);
@ -42,12 +43,7 @@ class _ProgressStylePageState extends State<ProgressStylePage> {
controller = new CalendarController( controller = new CalendarController(
extraDataMap: progressMap, extraDataMap: progressMap,
weekBarItemWidgetBuilder: () { );
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return ProgressStyleDayWidget(dateModel);
});
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {
@ -98,7 +94,12 @@ class _ProgressStylePageState extends State<ProgressStylePage> {
), ),
CalendarViewWidget( CalendarViewWidget(
calendarController: controller, calendarController: controller,
), weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return ProgressStyleDayWidget(dateModel);
}),
ValueListenableBuilder( ValueListenableBuilder(
valueListenable: selectText, valueListenable: selectText,
builder: (context, value, child) { builder: (context, value, child) {
@ -117,7 +118,7 @@ class _ProgressStylePageState extends State<ProgressStylePage> {
} }
class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleWeekBarItem extends BaseWeekBar {
List<String> weekList = ["", "", "", "", "", "", ""]; final List<String> weekList = ["", "", "", "", "", "", ""];
@override @override
Widget getWeekBarItem(int index) { Widget getWeekBarItem(int index) {

@ -0,0 +1,238 @@
import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
class RedStylePage extends StatefulWidget {
RedStylePage({Key key, this.title}) : super(key: key);
final String title;
@override
_RedStylePageState createState() => _RedStylePageState();
}
class _RedStylePageState extends State<RedStylePage> {
ValueNotifier<String> text;
ValueNotifier<String> selectText;
CalendarController controller;
Map<DateModel, String> customExtraData = {};
Color pinkColor = Color(0xffFF8291);
@override
void initState() {
super.initState();
controller = new CalendarController(
showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK,
extraDataMap: customExtraData);
controller.addMonthChangeListener(
(year, month) {
text.value = "$year$month";
},
);
controller.addOnCalendarSelectListener((dateModel) {
//
selectText.value =
"单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}";
});
text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}");
selectText = new ValueNotifier(
"单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}");
}
@override
Widget build(BuildContext context) {
var calendarWidget = CalendarViewWidget(
calendarController: controller,
margin: EdgeInsets.only(top: 20),
weekBarItemWidgetBuilder: () {
return CustomStyleWeekBarItem();
},
dayWidgetBuilder: (dateModel) {
return CustomStyleDayWidget(dateModel);
},
);
return SafeArea(
child: Scaffold(
appBar: AppBar(),
body: new Container(
color: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 20),
child: new Column(
crossAxisAlignment:CrossAxisAlignment.stretch ,
children: <Widget>[
SizedBox(
height: 20,
),
Stack(
alignment: Alignment.center,
children: <Widget>[
ValueListenableBuilder(
valueListenable: text,
builder: (context, value, child) {
return new Text(
"${text.value}",
style: TextStyle(
fontSize: 20,
color: Colors.black,
fontWeight: FontWeight.w700),
);
}),
Positioned(
left: 0,
child: Icon(
Icons.notifications,
color: pinkColor,
),
),
Positioned(
right: 40,
child: Icon(
Icons.search,
color: pinkColor,
),
),
Positioned(
right: 0,
child: Icon(
Icons.add,
color: pinkColor,
),
),
],
),
calendarWidget,
ValueListenableBuilder(
valueListenable: selectText,
builder: (context, value, child) {
return Padding(
padding: const EdgeInsets.all(20.0),
child: new Text(selectText.value),
);
}),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
controller.toggleExpandStatus();
},
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
),
);
}
}
class CustomStyleWeekBarItem extends BaseWeekBar {
final List<String> weekList = ["M", "T", "W", "T", "F", "S", "S"];
//build
@override
Widget build(BuildContext context) {
List<Widget> children = List();
var items = getWeekDayWidget();
children.add(Row(
children: items,
));
children.add(Divider(
color: Colors.grey,
));
return Column(
children: children,
);
}
@override
Widget getWeekBarItem(int index) {
return new Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: new Center(
child: new Text(
weekList[index],
style:
TextStyle(fontWeight: FontWeight.w700, color: Color(0xffBBC0C6)),
),
),
);
}
}
class CustomStyleDayWidget extends BaseCombineDayWidget {
CustomStyleDayWidget(DateModel dateModel) : super(dateModel);
final TextStyle normalTextStyle =
TextStyle(fontWeight: FontWeight.w700, color: Colors.black);
final TextStyle noIsCurrentMonthTextStyle =
TextStyle(fontWeight: FontWeight.w700, color: Colors.grey);
@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: dateModel.isCurrentMonth
? normalTextStyle
: noIsCurrentMonthTextStyle,
),
),
),
],
),
],
),
);
}
@override
Widget getSelectedWidget(DateModel dateModel) {
return Container(
// margin: EdgeInsets.all(8),
decoration: new BoxDecoration(
shape: BoxShape.circle,
color: Color(0xffFF8291),
),
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: TextStyle(color: Colors.white),
),
),
),
],
),
],
),
);
}
}

@ -129,7 +129,7 @@ packages:
name: provider name: provider
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.0+1" version: "3.1.0+1"
quiver: quiver:
dependency: transitive dependency: transitive
description: description:

@ -1,5 +1,5 @@
name: example name: example1
description: A new Flutter module. description: A new Flutter project.
# The following defines the version and build number for your application. # The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43 # A version number is three numbers separated by dots, like 1.2.43
@ -11,10 +11,6 @@ description: A new Flutter module.
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
#
# This version is used _only_ for the Runner app, which is used if you just do
# a `flutter run` or a `flutter make-host-app-editable`. It has no impact
# on any other native host app that you embed your Flutter project into.
version: 1.0.0+1 version: 1.0.0+1
environment: environment:
@ -27,28 +23,26 @@ dependencies:
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2 cupertino_icons: ^0.1.2
random_pk: any random_pk: ^0.0.3
flutter_custom_calendar: flutter_custom_calendar:
path: ../ path: ../
# flutter_custom_calendar:
# git:
# url: https://github.com/LXD312569496/flutter_custom_calendar.git
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
# For information on the generic Dart part of this file, see the # For information on the generic Dart part of this file, see the
# following page: https://www.dartlang.org/tools/pub/pubspec # following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter.
flutter: flutter:
# The following line ensures that the Material Icons font is # The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in # included with your application, so that you can use the icons in
# the material Icons class. # the material Icons class.
uses-material-design: true uses-material-design: true
# To add Flutter specific assets to your application, add an assets section, # To add assets to your application, add an assets section, like this:
# like this:
# assets: # assets:
# - images/a_dot_burr.jpeg # - images/a_dot_burr.jpeg
# - images/a_dot_ham.jpeg # - images/a_dot_ham.jpeg
@ -59,9 +53,9 @@ flutter:
# For details regarding adding assets from package dependencies, see # For details regarding adding assets from package dependencies, see
# https://flutter.dev/assets-and-images/#from-packages # https://flutter.dev/assets-and-images/#from-packages
# To add Flutter specific custom fonts to your application, add a fonts # To add custom fonts to your application, add a fonts section here,
# section here, in this "flutter" section. Each entry in this list should # in this "flutter" section. Each entry in this list should have a
# have a "family" key with the font family name, and a "fonts" key with 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 # list giving the asset and other descriptors for the font. For
# example: # example:
# fonts: # fonts:
@ -78,14 +72,3 @@ flutter:
# #
# For details regarding fonts from package dependencies, # For details regarding fonts from package dependencies,
# see https://flutter.dev/custom-fonts/#from-packages # see https://flutter.dev/custom-fonts/#from-packages
# This section identifies your Flutter project as a module meant for
# embedding in a native host app. These identifiers should _not_ ordinarily
# be changed after generation - they are used to ensure that the tooling can
# maintain consistency when adding or modifying assets and plugins.
# They also do not have any bearing on your native host application's
# identifiers, which may be completely independent or the same as these.
module:
androidPackage: com.donggua.example
iosBundleIdentifier: com.donggua.example

@ -8,7 +8,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:example/main.dart'; import 'package:example1/main.dart';
void main() { void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async { testWidgets('Counter increments smoke test', (WidgetTester tester) async {

@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>flutter_demo</title> <title>example1</title>
</head> </head>
<body> <body>
<script src="main.dart.js" type="application/javascript"></script> <script src="main.dart.js" type="application/javascript"></script>

@ -1,7 +1,10 @@
import 'dart:collection';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/cache_data.dart'; import 'package:flutter_custom_calendar/cache_data.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/constants/constants.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'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart';
import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart';
@ -14,13 +17,22 @@ import 'package:flutter_custom_calendar/widget/month_view.dart';
*/ */
class CalendarProvider extends ChangeNotifier { class CalendarProvider extends ChangeNotifier {
double _totalHeight; // double _totalHeight; //
Set<DateModel> selectedDateList = new Set(); //, HashSet<DateModel> selectedDateList = new HashSet<DateModel>(); //,
DateModel _selectDateModel; // DateModel _selectDateModel; //
ItemContainerState lastClickItemState; ItemContainerState lastClickItemState;
DateModel _lastClickDateModel; DateModel _lastClickDateModel;
double get totalHeight => _totalHeight; double get totalHeight => _totalHeight;
ValueNotifier<int> _generation =
new ValueNotifier(0); //int
ValueNotifier<int> get generation => _generation;
set generation(ValueNotifier<int> value) {
_generation = value;
}
set totalHeight(double value) { set totalHeight(double value) {
_totalHeight = value; _totalHeight = value;
} }
@ -95,26 +107,78 @@ class CalendarProvider extends ChangeNotifier {
// //
CalendarConfiguration calendarConfiguration; CalendarConfiguration calendarConfiguration;
void initData( void initData({
{Set<DateModel> selectedDateList, Set<DateModel> selectedDateList,
DateModel selectDateModel, DateModel selectDateModel,
CalendarConfiguration calendarConfiguration}) { CalendarConfiguration calendarConfiguration,
EdgeInsetsGeometry padding,
EdgeInsetsGeometry margin,
double itemSize,
double verticalSpacing,
DayWidgetBuilder dayWidgetBuilder,
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder,
}) {
LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider initData"); LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider initData");
if (selectedDateList != null) {
this.selectedDateList.addAll(selectedDateList);
}
this.selectDateModel = selectDateModel;
this.calendarConfiguration = calendarConfiguration; this.calendarConfiguration = calendarConfiguration;
print(
"calendarConfiguration.defaultSelectedDateList:${calendarConfiguration.defaultSelectedDateList}");
this
.selectedDateList
.addAll(this.calendarConfiguration.defaultSelectedDateList);
this.selectDateModel = this.calendarConfiguration.selectDateModel;
this.calendarConfiguration.padding = padding;
this.calendarConfiguration.margin = margin;
this.calendarConfiguration.itemSize = itemSize;
this.calendarConfiguration.verticalSpacing = verticalSpacing;
this.calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder;
this.calendarConfiguration.weekBarItemWidgetBuilder =
weekBarItemWidgetBuilder;
//lastClickDateModelitem //lastClickDateModelitem
this.lastClickDateModel = selectDateModel != null this.lastClickDateModel = selectDateModel != null
? selectDateModel ? selectDateModel
: DateModel.fromDateTime(DateTime.now()) : DateModel.fromDateTime(DateTime.now())
..day = 15; ..day = 15;
if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK) { //
if (calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_ONLY_WEEK ||
calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_WEEK_AND_MONTH) {
expandStatus = ValueNotifier(false); expandStatus = ValueNotifier(false);
} else { } else {
expandStatus = ValueNotifier(true); expandStatus = ValueNotifier(true);
} }
//itemitemSize/7/7paddingmargin
if (calendarConfiguration.itemSize == null) {
MediaQueryData mediaQueryData =
MediaQueryData.fromWindow(WidgetsBinding.instance.window);
if (mediaQueryData.orientation == Orientation.landscape) {
calendarConfiguration.itemSize = (mediaQueryData.size.height -
calendarConfiguration.padding.vertical -
calendarConfiguration.margin.vertical) /
7;
} else {
calendarConfiguration.itemSize = (mediaQueryData.size.width -
calendarConfiguration.padding.horizontal -
calendarConfiguration.margin.horizontal) /
7;
}
} else {
//itemSizeitemSize
}
//
if (calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_ONLY_MONTH ||
calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) {
int lineCount = DateUtil.getMonthViewLineCount(
calendarConfiguration.nowYear, calendarConfiguration.nowMonth);
totalHeight = calendarConfiguration.itemSize * (lineCount) +
calendarConfiguration.verticalSpacing * (lineCount - 1);
} else {
totalHeight = calendarConfiguration.itemSize;
}
} }
//退 //退

@ -1,6 +1,9 @@
import 'dart:collection';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter/foundation.dart';
/** /**
* *
@ -33,16 +36,19 @@ class CalendarConfiguration {
int maxSelectMonth; int maxSelectMonth;
int maxSelectDay; // int maxSelectDay; //
Set<DateModel> defaultSelectedDateList = new Set(); // DateModel selectDateModel; //item
HashSet<DateModel> defaultSelectedDateList; //set
int maxMultiSelectCount; // int maxMultiSelectCount; //
Map<DateModel, Object> extraDataMap = new Map(); // Map<DateModel, Object> extraDataMap = new Map(); //
/** /**
* UI * UI
*/ */
double itemSize; ///7
double verticalSpacing; //item10 double verticalSpacing; //item10
BoxDecoration boxDecoration; // BoxDecoration boxDecoration; //
double itemSize; ///7 EdgeInsetsGeometry padding;
EdgeInsetsGeometry margin;
// //
DayWidgetBuilder dayWidgetBuilder; //item DayWidgetBuilder dayWidgetBuilder; //item
@ -52,11 +58,16 @@ class CalendarConfiguration {
* *
*/ */
// //
OnMonthChange monthChange; // OnMonthChange monthChange; // ,multiMonthChanges
OnCalendarSelect calendarSelect; // OnCalendarSelect calendarSelect; //
OnMultiSelectOutOfRange multiSelectOutOfRange; // OnMultiSelectOutOfRange multiSelectOutOfRange; //
OnMultiSelectOutOfSize multiSelectOutOfSize; // OnMultiSelectOutOfSize multiSelectOutOfSize; //
ObserverList<OnMonthChange> monthChangeListeners =
ObserverList<OnMonthChange>(); //
ObserverList<OnWeekChange> weekChangeListeners =
ObserverList<OnWeekChange>(); //
/** /**
* *
*/ */
@ -64,6 +75,8 @@ class CalendarConfiguration {
List<DateModel> weekList = new List(); //list List<DateModel> weekList = new List(); //list
PageController monthController; //controller PageController monthController; //controller
PageController weekController; //controller PageController weekController; //controller
DateModel minSelectDate;
DateModel maxSelectDate;
CalendarConfiguration( CalendarConfiguration(
{this.selectMode, {this.selectMode,
@ -80,6 +93,7 @@ class CalendarConfiguration {
this.maxSelectMonth, this.maxSelectMonth,
this.maxSelectDay, this.maxSelectDay,
this.defaultSelectedDateList, this.defaultSelectedDateList,
this.selectDateModel,
this.maxMultiSelectCount, this.maxMultiSelectCount,
this.extraDataMap, this.extraDataMap,
this.monthList, this.monthList,
@ -87,7 +101,10 @@ class CalendarConfiguration {
this.monthController, this.monthController,
this.weekController, this.weekController,
this.verticalSpacing, this.verticalSpacing,
this.itemSize,this.showMode}); this.itemSize,
this.showMode,
this.padding,
this.margin});
@override @override
String toString() { String toString() {

@ -1,4 +1,4 @@
class Constants { class CalendarConstants {
// //
static const int MODE_SINGLE_SELECT = 1; static const int MODE_SINGLE_SELECT = 1;
@ -7,7 +7,8 @@ class Constants {
// //
static const int MODE_SHOW_ONLY_MONTH=1;// static const int MODE_SHOW_ONLY_MONTH=1;//
static const int MODE_SHOW_ONLY_WEEK=2;// static const int MODE_SHOW_ONLY_WEEK=2;//
static const int MODE_SHOW_WEEK_AND_MONTH=3;// static const int MODE_SHOW_WEEK_AND_MONTH=3;//
static const int MODE_SHOW_MONTH_AND_WEEK=4;//
/** /**

@ -1,3 +1,5 @@
import 'dart:collection';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
@ -31,29 +33,32 @@ class CalendarController {
PageController weekController; //controller PageController weekController; //controller
CalendarController( CalendarController(
{int selectMode = Constants.MODE_SINGLE_SELECT, {int selectMode = CalendarConstants.MODE_SINGLE_SELECT,
int showMode = Constants.MODE_SHOW_ONLY_MONTH, int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH,
DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget,
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget,
int minYear = 1971, int minYear = 1971,
int maxYear = 2055, int maxYear = 2055,
int minYearMonth = 1, int minYearMonth = 1,
int maxYearMonth = 12, int maxYearMonth = 12,
int nowYear = -1, int nowYear,
int nowMonth = -1, int nowMonth,
int minSelectYear = 1971, int minSelectYear = 1971,
int minSelectMonth = 1, int minSelectMonth = 1,
int minSelectDay = 1, int minSelectDay = 1,
int maxSelectYear = 2055, int maxSelectYear = 2055,
int maxSelectMonth = 12, int maxSelectMonth = 12,
int maxSelectDay = 30, int maxSelectDay = 30,
Set<DateTime> selectedDateTimeList = EMPTY_SET, Set<DateTime> selectedDateTimeList = EMPTY_SET, //item
DateModel selectDateModel, DateModel selectDateModel, //item
int maxMultiSelectCount = 9999, int maxMultiSelectCount = 9999,
double verticalSpacing = 10,
double itemSize,
Map<DateModel, Object> extraDataMap = EMPTY_MAP}) { Map<DateModel, Object> extraDataMap = EMPTY_MAP}) {
LogUtil.log(TAG: this.runtimeType, message: "init CalendarConfiguration"); LogUtil.log(TAG: this.runtimeType, message: "init CalendarConfiguration");
//
if (nowYear == null) {
nowYear = DateTime.now().year;
}
if (nowMonth == null) {
nowMonth = DateTime.now().month;
}
calendarConfiguration = CalendarConfiguration( calendarConfiguration = CalendarConfiguration(
selectMode: selectMode, selectMode: selectMode,
showMode: showMode, showMode: showMode,
@ -70,18 +75,26 @@ class CalendarController {
maxSelectMonth: maxSelectMonth, maxSelectMonth: maxSelectMonth,
extraDataMap: extraDataMap, extraDataMap: extraDataMap,
maxSelectDay: maxSelectDay, maxSelectDay: maxSelectDay,
verticalSpacing: verticalSpacing, maxMultiSelectCount: maxMultiSelectCount,
itemSize: itemSize); selectDateModel: selectDateModel);
calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder;
calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder;
if (selectedDateTimeList != null && selectedDateTimeList.isNotEmpty) { calendarConfiguration.defaultSelectedDateList = new HashSet<DateModel>();
calendarConfiguration.defaultSelectedDateList calendarConfiguration.defaultSelectedDateList
.addAll(selectedDateTimeList.map((dateTime) { .addAll(selectedDateTimeList.map((dateTime) {
return DateModel.fromDateTime(dateTime); return DateModel.fromDateTime(dateTime);
}).toSet()); }).toSet());
} //provider
calendarProvider.selectDateModel = selectDateModel;
calendarProvider.selectedDateList =
calendarConfiguration.defaultSelectedDateList;
calendarConfiguration.minSelectDate = DateModel.fromDateTime(DateTime(
calendarConfiguration.minSelectYear,
calendarConfiguration.minSelectMonth,
calendarConfiguration.minSelectDay));
calendarConfiguration.maxSelectDate = DateModel.fromDateTime(DateTime(
calendarConfiguration.maxSelectYear,
calendarConfiguration.maxSelectMonth,
calendarConfiguration.maxSelectDay));
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
@ -93,8 +106,7 @@ class CalendarController {
maxYearMonth, maxYearMonth,
))}"); ))}");
if (showMode == Constants.MODE_SHOW_ONLY_MONTH || if (showMode != CalendarConstants.MODE_SHOW_ONLY_WEEK) {
showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) {
//pageController,initialPage //pageController,initialPage
int initialPage = 0; int initialPage = 0;
int nowMonthIndex = 0; int nowMonthIndex = 0;
@ -111,11 +123,6 @@ class CalendarController {
dateModel.year = i; dateModel.year = i;
dateModel.month = j; dateModel.month = j;
//
if (nowYear == -1 || nowMonth == -1) {
nowYear = DateTime.now().year;
nowMonth = DateTime.now().month;
}
if (i == nowYear && j == nowMonth) { if (i == nowYear && j == nowMonth) {
initialPage = nowMonthIndex; initialPage = nowMonthIndex;
} }
@ -129,15 +136,13 @@ class CalendarController {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: message:
"初始化月份视图的信息:一共有${monthList.length}个月initialPage为${nowMonthIndex}"); "初始化月份视图的信息:一共有${monthList.length}个月initialPage为$nowMonthIndex");
} }
if (showMode == Constants.MODE_SHOW_ONLY_WEEK || if (showMode != CalendarConstants.MODE_SHOW_ONLY_MONTH) {
showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) {
// //
///72 ///72
int initialWeekPage = 0; int initialWeekPage = 0;
int nowWeekIndex = 0;
weekList.clear(); weekList.clear();
// //
if (nowYear == -1 || nowMonth == -1) { if (nowYear == -1 || nowMonth == -1) {
@ -169,7 +174,7 @@ class CalendarController {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: message:
"初始化星期视图的信息:一共有${weekList.length}个星期initialPage为${initialWeekPage}"); "初始化星期视图的信息:一共有${weekList.length}个星期initialPage为$initialWeekPage");
this.weekController = new PageController(initialPage: initialWeekPage); this.weekController = new PageController(initialPage: initialWeekPage);
} }
@ -177,13 +182,17 @@ class CalendarController {
calendarConfiguration.weekList = weekList; calendarConfiguration.weekList = weekList;
calendarConfiguration.monthController = monthController; calendarConfiguration.monthController = monthController;
calendarConfiguration.weekController = weekController; calendarConfiguration.weekController = weekController;
calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder; }
calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder;
//
void addWeekChangeListener(OnWeekChange listener){
this.calendarConfiguration.weekChangeListeners.add(listener);
} }
// //
void addMonthChangeListener(OnMonthChange listener) { void addMonthChangeListener(OnMonthChange listener) {
this.calendarConfiguration.monthChange = listener; // this.calendarConfiguration.monthChange = listener;
this.calendarConfiguration.monthChangeListeners.add(listener);
} }
// //
@ -216,6 +225,25 @@ class CalendarController {
}); });
} }
//extraDataMap
void changeExtraData(Map<DateModel, Object> newMap) {
this.calendarConfiguration.extraDataMap = newMap;
this.calendarProvider.generation.value++;
}
//item
void changeDefaultSelectedDateList(Set<DateModel> defaultSelectedDateList) {
this.calendarConfiguration.defaultSelectedDateList =
defaultSelectedDateList;
this.calendarProvider.generation.value++;
}
//item
void changeDefaultSelectedDateModel(DateModel dateModel) {
this.calendarProvider.selectDateModel = dateModel;
this.calendarProvider.generation.value++;
}
/** /**
* *
*/ */
@ -229,8 +257,11 @@ class CalendarController {
} else { } else {
calendarProvider.calendarConfiguration.monthController calendarProvider.calendarConfiguration.monthController
.previousPage(duration: DEFAULT_DURATION, curve: Curves.ease); .previousPage(duration: DEFAULT_DURATION, curve: Curves.ease);
calendarProvider.calendarConfiguration.monthChange( calendarProvider.calendarConfiguration.monthChangeListeners
monthList[currentIndex-1].year, monthList[currentIndex-1].month); .forEach((listener) {
listener(monthList[currentIndex - 1].year,
monthList[currentIndex - 1].month);
});
DateModel temp = new DateModel(); DateModel temp = new DateModel();
temp.year = monthList[currentIndex].year; temp.year = monthList[currentIndex].year;
temp.month = monthList[currentIndex].month; temp.month = monthList[currentIndex].month;
@ -267,8 +298,12 @@ class CalendarController {
} else { } else {
calendarProvider.calendarConfiguration.monthController calendarProvider.calendarConfiguration.monthController
.nextPage(duration: DEFAULT_DURATION, curve: Curves.ease); .nextPage(duration: DEFAULT_DURATION, curve: Curves.ease);
calendarProvider.calendarConfiguration.monthChange( calendarProvider.calendarConfiguration.monthChangeListeners
monthList[currentIndex+1].year, monthList[currentIndex+1].month); .forEach((listener) {
listener(monthList[currentIndex + 1].year,
monthList[currentIndex + 1].month);
});
DateModel temp = new DateModel(); DateModel temp = new DateModel();
temp.year = monthList[currentIndex].year; temp.year = monthList[currentIndex].year;
temp.month = monthList[currentIndex].month; temp.month = monthList[currentIndex].month;
@ -467,6 +502,8 @@ class CalendarController {
monthList.clear(); monthList.clear();
weekList.clear(); weekList.clear();
calendarProvider.clearData(); calendarProvider.clearData();
calendarConfiguration.weekChangeListeners=null;
calendarConfiguration.monthChangeListeners=null;
} }
} }
@ -502,6 +539,11 @@ bool defaultInRange(DateModel dateModel) {
return true; return true;
} }
/**
*
*/
typedef void OnWeekChange(int year, int month);
/** /**
* *
*/ */

@ -45,7 +45,7 @@ class DateModel {
// //
String get traditionFestival => String get traditionFestival =>
LunarUtil.getTraditionFestival(year, month, day); LunarUtil.getTraditionFestival(lunarYear, lunarMonth, lunarDay);
bool isCurrentMonth; // bool isCurrentMonth; //
@ -124,3 +124,14 @@ class DateModel {
return this.getDateTime().isBefore(dateModel.getDateTime()); return this.getDateTime().isBefore(dateModel.getDateTime());
} }
} }
class X {
var _y;
get y => null == _y ? initY() : _y;
initY() {
//do some computation
_y = "result";
}
}

@ -4,7 +4,7 @@ import 'package:flutter/cupertino.dart';
* 便 * 便
*/ */
class LogUtil { class LogUtil {
static bool _enableLog = true; // static bool _enableLog = false; //
static set enableLog(bool value) { static set enableLog(bool value) {
_enableLog = value; _enableLog = value;

@ -1,6 +1,3 @@
import 'dart:developer';
import 'dart:math';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart';
@ -168,7 +165,11 @@ class DateUtil {
if (extraDataMap?.isNotEmpty == true) { if (extraDataMap?.isNotEmpty == true) {
if (extraDataMap.containsKey(dateModel)) { if (extraDataMap.containsKey(dateModel)) {
dateModel.extraData = extraDataMap[dateModel]; dateModel.extraData = extraDataMap[dateModel];
}else{
dateModel.extraData=null;
} }
}else{
dateModel.extraData=null;
} }
result.add(dateModel); result.add(dateModel);

@ -908,7 +908,7 @@ class LunarUtil {
if (day == 1) { if (day == 1) {
return numToChineseMonth(month, leap); return numToChineseMonth(month, leap);
} }
return Constants.LUNAR_DAY_TEXT[day - 1]; return CalendarConstants.LUNAR_DAY_TEXT[day - 1];
} }
/** /**
@ -920,9 +920,9 @@ class LunarUtil {
*/ */
static String numToChineseMonth(int month, int leap) { static String numToChineseMonth(int month, int leap) {
if (leap == 1) { if (leap == 1) {
return "" + Constants.LUNAR_MONTH_TEXT[month - 1]; return "" + CalendarConstants.LUNAR_MONTH_TEXT[month - 1];
} }
return Constants.LUNAR_MONTH_TEXT[month - 1]; return CalendarConstants.LUNAR_MONTH_TEXT[month - 1];
} }
static String getString(int month, int day) { static String getString(int month, int day) {

@ -56,7 +56,7 @@ class CustomDayWidgetPainter extends CustomPainter {
* widgetitem * widgetitem
*/ */
abstract class BaseCombineDayWidget extends StatelessWidget { abstract class BaseCombineDayWidget extends StatelessWidget {
DateModel dateModel; final DateModel dateModel;
BaseCombineDayWidget(this.dateModel); BaseCombineDayWidget(this.dateModel);

@ -3,7 +3,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/constants/constants.dart'; import 'package:flutter_custom_calendar/constants/constants.dart';
import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart';
import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart';
import 'package:flutter_custom_calendar/widget/month_view_pager.dart'; import 'package:flutter_custom_calendar/widget/month_view_pager.dart';
@ -17,13 +16,35 @@ import 'package:provider/provider.dart';
//StatefulWidgetStatelessWidget //StatefulWidgetStatelessWidget
class CalendarViewWidget extends StatefulWidget { class CalendarViewWidget extends StatefulWidget {
// //
BoxDecoration boxDecoration; final BoxDecoration boxDecoration;
//paddingmargin
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry margin;
///7
final double itemSize;
//item10
final double verticalSpacing;
//item
final DayWidgetBuilder dayWidgetBuilder;
final WeekBarItemWidgetBuilder weekBarItemWidgetBuilder;
// //
final CalendarController calendarController; final CalendarController calendarController;
CalendarViewWidget( CalendarViewWidget(
{Key key, @required this.calendarController, this.boxDecoration}) {Key key,
this.dayWidgetBuilder = defaultCustomDayWidget,
this.weekBarItemWidgetBuilder = defaultWeekBarWidget,
@required this.calendarController,
this.boxDecoration,
this.padding = EdgeInsets.zero,
this.margin = EdgeInsets.zero,
this.verticalSpacing = 10,
this.itemSize})
: super(key: key); : super(key: key);
@override @override
@ -35,14 +56,20 @@ class _CalendarViewWidgetState extends State<CalendarViewWidget> {
void initState() { void initState() {
//provider //provider
widget.calendarController.calendarProvider.initData( widget.calendarController.calendarProvider.initData(
calendarConfiguration: widget.calendarController.calendarConfiguration); calendarConfiguration: widget.calendarController.calendarConfiguration,
padding: widget.padding,
margin: widget.margin,
itemSize: widget.itemSize,
verticalSpacing: widget.verticalSpacing,
dayWidgetBuilder: widget.dayWidgetBuilder,
weekBarItemWidgetBuilder: widget.weekBarItemWidgetBuilder);
super.initState(); super.initState();
} }
@override @override
void dispose() { void dispose() {
widget.calendarController.clearData(); // widget.calendarController.clearData();
super.dispose(); super.dispose();
} }
@ -53,6 +80,8 @@ class _CalendarViewWidgetState extends State<CalendarViewWidget> {
child: Container( child: Container(
// //
decoration: widget.boxDecoration, decoration: widget.boxDecoration,
padding: widget.padding,
margin: widget.margin,
//使constsetStatewidget //使constsetStatewidget
child: CalendarContainer(widget.calendarController)), child: CalendarContainer(widget.calendarController)),
); );
@ -73,42 +102,49 @@ class CalendarContainerState extends State<CalendarContainer>
double itemHeight; double itemHeight;
double totalHeight; double totalHeight;
bool expand = true; bool expand;
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
var state = CrossFadeState.showFirst;
List<Widget> widgets = []; List<Widget> widgets = [];
int index = 0; int index = 0;
@override @override
void initState() { void initState() {
super.initState();
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
expand = calendarProvider.expandStatus.value; expand = calendarProvider.expandStatus.value;
if (calendarProvider.calendarConfiguration.showMode == if (calendarProvider.calendarConfiguration.showMode ==
Constants.MODE_SHOW_ONLY_WEEK) { CalendarConstants.MODE_SHOW_ONLY_WEEK) {
widgets.add(const WeekViewPager()); widgets.add(const WeekViewPager());
} else if (calendarProvider.calendarConfiguration.showMode == } else if (calendarProvider.calendarConfiguration.showMode ==
Constants.MODE_SHOW_WEEK_AND_MONTH) { CalendarConstants.MODE_SHOW_WEEK_AND_MONTH) {
widgets.add(const MonthViewPager());
widgets.add(const WeekViewPager());
index = 1;
} else if (calendarProvider.calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) {
widgets.add(const MonthViewPager()); widgets.add(const MonthViewPager());
widgets.add(const WeekViewPager()); widgets.add(const WeekViewPager());
index = 0;
} else { } else {
// //
widgets.add(const MonthViewPager()); widgets.add(const MonthViewPager());
} }
expand = calendarProvider.expandStatus.value;
// //
if (calendarProvider.calendarConfiguration.showMode == if (calendarProvider.calendarConfiguration.showMode ==
Constants.MODE_SHOW_WEEK_AND_MONTH) { CalendarConstants.MODE_SHOW_WEEK_AND_MONTH ||
calendarProvider.calendarConfiguration.showMode ==
CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) {
calendarProvider.expandStatus.addListener(() { calendarProvider.expandStatus.addListener(() {
setState(() { setState(() {
print(
"calendarProvider.expandStatus.value:${calendarProvider.expandStatus.value}");
expand = calendarProvider.expandStatus.value; expand = calendarProvider.expandStatus.value;
state = (state == CrossFadeState.showSecond
? CrossFadeState.showFirst
: CrossFadeState.showSecond);
if (expand) { if (expand) {
index = 0; index = 0;
// //
@ -122,44 +158,34 @@ class CalendarContainerState extends State<CalendarContainer>
} }
}); });
}); });
} else {
index = 0;
} }
// widget.calendarController.addMonthChangeListener((year, month) { widget.calendarController.addMonthChangeListener((year, month) {
// if (widget.calendarController.calendarProvider.calendarConfiguration if (widget.calendarController.calendarProvider.calendarConfiguration
// .showMode != .showMode !=
// Constants.MODE_SHOW_ONLY_WEEK) { CalendarConstants.MODE_SHOW_ONLY_WEEK) {
// //setState使 //setState使
// int lineCount = DateUtil.getMonthViewLineCount(year, month); int lineCount = DateUtil.getMonthViewLineCount(year, month);
// double newHeight = itemHeight * lineCount + double newHeight = itemHeight * (lineCount) +
// calendarProvider.calendarConfiguration.verticalSpacing * calendarProvider.calendarConfiguration.verticalSpacing *
// (lineCount - 1); (lineCount - 1);
// if (totalHeight.toInt() != newHeight.toInt()) { LogUtil.log(
// LogUtil.log( TAG: this.runtimeType,
// TAG: this.runtimeType, message: "totalHeight:$totalHeight,newHeight:$newHeight");
// message: "totalHeight:$totalHeight,newHeight:$newHeight"); if (totalHeight.toInt() != newHeight.toInt()) {
// LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化");
// LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); setState(() {
// setState(() { totalHeight = newHeight;
// totalHeight = newHeight; });
// });
// }
// }
// });
//,,:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand.
MediaQueryData mediaQueryData =
MediaQueryData.fromWindow(WidgetsBinding.instance.window);
itemHeight = calendarProvider.calendarConfiguration.itemSize ??
mediaQueryData.orientation == Orientation.landscape
? mediaQueryData.size.height / 10
: mediaQueryData.size.width / 7;
if (calendarProvider.totalHeight == null) {
calendarProvider.totalHeight = itemHeight * 6 +
calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1);
} }
} }
});
itemHeight = calendarProvider.calendarConfiguration.itemSize;
totalHeight = calendarProvider.totalHeight;
}
@override @override
void dispose() { void dispose() {
@ -169,13 +195,6 @@ class CalendarContainerState extends State<CalendarContainer>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
LogUtil.log(TAG: this.runtimeType, message: "CalendarContainerState build"); LogUtil.log(TAG: this.runtimeType, message: "CalendarContainerState build");
//,,:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand.
// itemHeight = calendarProvider.calendarConfiguration.itemSize ??
// MediaQuery.of(context).size.width / 7;
if (totalHeight == null) {
totalHeight = itemHeight * 6 +
calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1);
}
return Container( return Container(
width: itemHeight * 7, width: itemHeight * 7,
child: new Column( child: new Column(

@ -47,7 +47,7 @@ class DefaultWeekBar extends BaseWeekBar {
height: 40, height: 40,
alignment: Alignment.center, alignment: Alignment.center,
child: new Text( child: new Text(
Constants.WEEK_LIST[index], CalendarConstants.WEEK_LIST[index],
style: topWeekTextStyle, style: topWeekTextStyle,
), ),
); );

@ -1,32 +0,0 @@
import 'package:flutter/material.dart';
/**
*
*/
class FastClickWidget extends StatelessWidget {
final int between_time = 500; //500ms
Function onTap;
Widget child;
FastClickWidget({@required this.onTap, @required this.child});
int lastClickTime = 0;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (lastClickTime == 0 ||
DateTime.now().millisecondsSinceEpoch - lastClickTime >
between_time) {
onTap();
lastClickTime = DateTime.now().millisecondsSinceEpoch;
} else {
//500ms
}
},
child: child,
);
}
}

@ -1,5 +1,3 @@
import 'dart:developer';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/cache_data.dart'; import 'package:flutter_custom_calendar/cache_data.dart';
@ -22,11 +20,12 @@ class MonthView extends StatefulWidget {
final CalendarConfiguration configuration; final CalendarConfiguration configuration;
const MonthView({ const MonthView({
Key key,
@required this.year, @required this.year,
@required this.month, @required this.month,
this.day, this.day,
this.configuration, this.configuration,
}); }) : super(key: key);
@override @override
_MonthViewState createState() => _MonthViewState(); _MonthViewState createState() => _MonthViewState();
@ -34,30 +33,14 @@ class MonthView extends StatefulWidget {
class _MonthViewState extends State<MonthView> class _MonthViewState extends State<MonthView>
with AutomaticKeepAliveClientMixin { with AutomaticKeepAliveClientMixin {
List<DateModel> items; List<DateModel> items = List();
int lineCount; int lineCount;
double itemHeight;
double totalHeight;
double mainSpacing = 10;
DateModel minSelectDate;
DateModel maxSelectDate;
Map<DateModel, Object> extraDataMap; // Map<DateModel, Object> extraDataMap; //
@override @override
void initState() { void initState() {
super.initState(); super.initState();
minSelectDate = DateModel.fromDateTime(DateTime(
widget.configuration.minSelectYear,
widget.configuration.minSelectMonth,
widget.configuration.minSelectDay));
maxSelectDate = DateModel.fromDateTime(DateTime(
widget.configuration.maxSelectYear,
widget.configuration.maxSelectMonth,
widget.configuration.maxSelectDay));
extraDataMap = widget.configuration.extraDataMap; extraDataMap = widget.configuration.extraDataMap;
DateModel firstDayOfMonth = DateModel firstDayOfMonth =
@ -68,42 +51,64 @@ class _MonthViewState extends State<MonthView>
items = CacheData.getInstance().monthListCache[firstDayOfMonth]; items = CacheData.getInstance().monthListCache[firstDayOfMonth];
} else { } else {
LogUtil.log(TAG: this.runtimeType, message: "缓存中无数据"); LogUtil.log(TAG: this.runtimeType, message: "缓存中无数据");
items = DateUtil.initCalendarForMonthView( getItems().then((_){
widget.year, widget.month, DateTime.now(), DateTime.sunday,
minSelectDate: minSelectDate,
maxSelectDate: maxSelectDate,
extraDataMap: extraDataMap);
CacheData.getInstance().monthListCache[firstDayOfMonth] = items; CacheData.getInstance().monthListCache[firstDayOfMonth] = items;
});
} }
lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month);
//,generation
WidgetsBinding.instance.addPostFrameCallback((callback) {
Provider.of<CalendarProvider>(context, listen: false)
.generation
.addListener(() async {
extraDataMap = widget.configuration.extraDataMap;
await getItems();
});
});
}
Future getItems() async {
items = await compute(initCalendarForMonthView, {
'year': widget.year,
'month': widget.month,
'minSelectDate': widget.configuration.minSelectDate,
'maxSelectDate': widget.configuration.maxSelectDate,
'extraDataMap': extraDataMap
});
setState(() {});
}
static Future<List<DateModel>> initCalendarForMonthView(Map map) async {
return DateUtil.initCalendarForMonthView(
map['year'], map['month'], DateTime.now(), DateTime.sunday,
minSelectDate: map['minSelectDate'],
maxSelectDate: map['maxSelectDate'],
extraDataMap: map['extraDataMap']);
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
LogUtil.log(TAG: this.runtimeType, message: "_MonthViewState build"); LogUtil.log(TAG: this.runtimeType, message: "_MonthViewState build");
itemHeight = MediaQuery.of(context).size.width / 7;
totalHeight = itemHeight * lineCount + mainSpacing * (lineCount - 1);
return Container(height: totalHeight, child: getView());
}
Widget getView() {
CalendarProvider calendarProvider = CalendarProvider calendarProvider =
Provider.of<CalendarProvider>(context, listen: false); Provider.of<CalendarProvider>(context, listen: false);
CalendarConfiguration configuration = CalendarConfiguration configuration =
calendarProvider.calendarConfiguration; calendarProvider.calendarConfiguration;
return new GridView.builder( return new GridView.builder(
physics: NeverScrollableScrollPhysics(), addAutomaticKeepAlives: true,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( padding: EdgeInsets.zero,
crossAxisCount: 7, mainAxisSpacing: 10), physics: const NeverScrollableScrollPhysics(),
itemCount: 7 * lineCount, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7, mainAxisSpacing: configuration.verticalSpacing),
itemCount: items.isEmpty ? 0 : 7 * lineCount,
itemBuilder: (context, index) { itemBuilder: (context, index) {
DateModel dateModel = items[index]; DateModel dateModel = items[index];
// //
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) {
if (calendarProvider.selectedDateList.contains(dateModel)) { if (calendarProvider.selectedDateList.contains(dateModel)) {
dateModel.isSelected = true; dateModel.isSelected = true;
} else { } else {
@ -119,8 +124,8 @@ class _MonthViewState extends State<MonthView>
return ItemContainer( return ItemContainer(
dateModel: dateModel, dateModel: dateModel,
// configuration: configuration, key: ObjectKey(
// calendarProvider: calendarProvider, dateModel), //使objectKey1flutter2statefulElementstate
); );
}); });
} }
@ -135,9 +140,6 @@ class _MonthViewState extends State<MonthView>
class ItemContainer extends StatefulWidget { class ItemContainer extends StatefulWidget {
final DateModel dateModel; final DateModel dateModel;
// CalendarConfiguration configuration;
// CalendarProvider calendarProvider;
const ItemContainer({ const ItemContainer({
Key key, Key key,
this.dateModel, this.dateModel,
@ -159,11 +161,36 @@ class ItemContainerState extends State<ItemContainer> {
super.initState(); super.initState();
dateModel = widget.dateModel; dateModel = widget.dateModel;
isSelected = ValueNotifier(dateModel.isSelected); isSelected = ValueNotifier(dateModel.isSelected);
//
// WidgetsBinding.instance.addPostFrameCallback((callback) {
// if (configuration.selectMode == CalendarConstants.MODE_SINGLE_SELECT &&
// dateModel.isSelected) {
// calendarProvider.lastClickItemState = this;
// }
// });
}
/**
* item
*/
void refreshItem() {
/**
Exception caught by gesture
The following assertion was thrown while handling a gesture:
setState() called after dispose()
*/
if (mounted) {
setState(() {
dateModel.isSelected = !dateModel.isSelected;
// isSelected.value = !isSelected.value;
});
}
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// LogUtil.log(TAG: this.runtimeType,message: "ItemContainerState build"); // LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState build");
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
configuration = calendarProvider.calendarConfiguration; configuration = calendarProvider.calendarConfiguration;
@ -178,7 +205,7 @@ class ItemContainerState extends State<ItemContainer> {
// //
if (!dateModel.isInRange) { if (!dateModel.isInRange) {
// //
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) {
configuration.multiSelectOutOfRange(); configuration.multiSelectOutOfRange();
} }
return; return;
@ -186,17 +213,18 @@ class ItemContainerState extends State<ItemContainer> {
calendarProvider.lastClickDateModel = dateModel; calendarProvider.lastClickDateModel = dateModel;
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) {
if (calendarProvider.selectedDateList.contains(dateModel)) {
calendarProvider.selectedDateList.remove(dateModel);
} else {
// //
if (calendarProvider.selectedDateList.length == if (calendarProvider.selectedDateList.length ==
configuration.maxMultiSelectCount) { configuration.maxMultiSelectCount) {
if (configuration.multiSelectOutOfSize != null) {
configuration.multiSelectOutOfSize(); configuration.multiSelectOutOfSize();
}
return; return;
} }
if (calendarProvider.selectedDateList.contains(dateModel)) {
calendarProvider.selectedDateList.remove(dateModel);
} else {
calendarProvider.selectedDateList.add(dateModel); calendarProvider.selectedDateList.add(dateModel);
} }
configuration.calendarSelect(dateModel); configuration.calendarSelect(dateModel);
@ -208,36 +236,35 @@ class ItemContainerState extends State<ItemContainer> {
configuration.calendarSelect(dateModel); configuration.calendarSelect(dateModel);
//item //item
if (calendarProvider.lastClickItemState != this) {
calendarProvider.lastClickItemState?.refreshItem(); calendarProvider.lastClickItemState?.refreshItem();
calendarProvider.lastClickItemState = this; calendarProvider.lastClickItemState = this;
} }
}
refreshItem(); refreshItem();
}, },
child: configuration.dayWidgetBuilder(dateModel), child: configuration.dayWidgetBuilder(dateModel),
// child: ValueListenableBuilder(
// valueListenable: isSelected,
// builder: (BuildContext context, bool value, Widget child) {
// return configuration.dayWidgetBuilder(dateModel);
// }),
); );
} }
/** @override
* item void deactivate() {
*/ // LogUtil.log(
void refreshItem() { // TAG: this.runtimeType, message: "ItemContainerState deactivate");
/** super.deactivate();
* }
Exception caught by gesture
The following assertion was thrown while handling a gesture: @override
setState() called after dispose() void dispose() {
*/ // LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState dispose");
if (mounted) { super.dispose();
setState(() {
dateModel.isSelected = !dateModel.isSelected;
// isSelected.value = !isSelected.value;
});
} }
@override
void didUpdateWidget(ItemContainer oldWidget) {
// LogUtil.log(
// TAG: this.runtimeType, message: "ItemContainerState didUpdateWidget");
super.didUpdateWidget(oldWidget);
} }
} }

@ -1,10 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/constants/constants.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart';
import 'package:flutter_custom_calendar/utils/date_util.dart';
import 'package:flutter_custom_calendar/widget/month_view.dart'; import 'package:flutter_custom_calendar/widget/month_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -15,11 +13,13 @@ class MonthViewPager extends StatefulWidget {
_MonthViewPagerState createState() => _MonthViewPagerState(); _MonthViewPagerState createState() => _MonthViewPagerState();
} }
class _MonthViewPagerState extends State<MonthViewPager> { class _MonthViewPagerState extends State<MonthViewPager>
with AutomaticKeepAliveClientMixin {
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
@override @override
void initState() { void initState() {
super.initState();
LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager initState"); LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager initState");
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
@ -57,6 +57,8 @@ class _MonthViewPagerState extends State<MonthViewPager> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager build");
// CalendarProvider,listenfalse // CalendarProvider,listenfalse
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
CalendarConfiguration configuration = CalendarConfiguration configuration =
@ -69,7 +71,9 @@ class _MonthViewPagerState extends State<MonthViewPager> {
} }
// //
DateModel dateModel = configuration.monthList[position]; DateModel dateModel = configuration.monthList[position];
configuration.monthChange(dateModel.year, dateModel.month); configuration.monthChangeListeners.forEach((listener) {
listener(dateModel.year, dateModel.month);
});
// //
if (calendarProvider.lastClickDateModel != null || if (calendarProvider.lastClickDateModel != null ||
calendarProvider.lastClickDateModel.month != dateModel.month) { calendarProvider.lastClickDateModel.month != dateModel.month) {
@ -79,24 +83,6 @@ class _MonthViewPagerState extends State<MonthViewPager> {
temp.day = configuration.monthList[position].day + 14; temp.day = configuration.monthList[position].day + 14;
calendarProvider.lastClickDateModel = temp; calendarProvider.lastClickDateModel = temp;
} }
//使PageView
if (calendarProvider.calendarConfiguration.showMode !=
Constants.MODE_SHOW_ONLY_WEEK) {
//setState使
int lineCount =
DateUtil.getMonthViewLineCount(dateModel.year, dateModel.month);
double newHeight = (calendarProvider.calendarConfiguration.itemSize ??
MediaQuery.of(context).size.width / 7) *
lineCount +
calendarProvider.calendarConfiguration.verticalSpacing *
(lineCount - 1);
if (calendarProvider.totalHeight.toInt() != newHeight.toInt()) {
LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化");
calendarProvider.totalHeight = newHeight;
// calendarProvider.changeTotalHeight(newHeight);
}
}
}, },
controller: configuration.monthController, controller: configuration.monthController,
itemBuilder: (context, index) { itemBuilder: (context, index) {
@ -110,4 +96,7 @@ class _MonthViewPagerState extends State<MonthViewPager> {
itemCount: configuration.monthList.length, itemCount: configuration.monthList.length,
); );
} }
@override
bool get wantKeepAlive => true;
} }

@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/constants/constants.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'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart';
import 'package:flutter_custom_calendar/widget/month_view.dart'; import 'package:flutter_custom_calendar/widget/month_view.dart';
@ -30,29 +29,32 @@ class WeekView extends StatefulWidget {
class _WeekViewState extends State<WeekView> { class _WeekViewState extends State<WeekView> {
List<DateModel> items; List<DateModel> items;
DateModel minSelectDate;
DateModel maxSelectDate;
Map<DateModel, Object> extraDataMap; // Map<DateModel, Object> extraDataMap; //
@override @override
void initState() { void initState() {
super.initState(); super.initState();
minSelectDate = DateModel.fromDateTime(DateTime(
widget.configuration.minSelectYear,
widget.configuration.minSelectMonth,
widget.configuration.minSelectDay));
maxSelectDate = DateModel.fromDateTime(DateTime(
widget.configuration.maxSelectYear,
widget.configuration.maxSelectMonth,
widget.configuration.maxSelectDay));
extraDataMap = widget.configuration.extraDataMap; extraDataMap = widget.configuration.extraDataMap;
items = DateUtil.initCalendarForWeekView( items = DateUtil.initCalendarForWeekView(
widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0, widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0,
minSelectDate: minSelectDate, minSelectDate: widget.configuration.minSelectDate,
maxSelectDate: maxSelectDate, maxSelectDate: widget.configuration.maxSelectDate,
extraDataMap: extraDataMap); extraDataMap: extraDataMap);
//,generation
WidgetsBinding.instance.addPostFrameCallback((callback) {
Provider.of<CalendarProvider>(context, listen: false)
.generation
.addListener(() async {
items = DateUtil.initCalendarForWeekView(
widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0,
minSelectDate: widget.configuration.minSelectDate,
maxSelectDate: widget.configuration.maxSelectDate,
extraDataMap: extraDataMap);
setState(() {});
});
});
} }
@override @override
@ -72,7 +74,7 @@ class _WeekViewState extends State<WeekView> {
itemBuilder: (context, index) { itemBuilder: (context, index) {
DateModel dateModel = items[index]; DateModel dateModel = items[index];
// //
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) {
if (calendarProvider.selectedDateList.contains(dateModel)) { if (calendarProvider.selectedDateList.contains(dateModel)) {
dateModel.isSelected = true; dateModel.isSelected = true;
} else { } else {

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart';
import 'package:flutter_custom_calendar/widget/week_view.dart'; import 'package:flutter_custom_calendar/widget/week_view.dart';
@ -14,7 +13,8 @@ class WeekViewPager extends StatefulWidget {
_WeekViewPagerState createState() => _WeekViewPagerState(); _WeekViewPagerState createState() => _WeekViewPagerState();
} }
class _WeekViewPagerState extends State<WeekViewPager> { class _WeekViewPagerState extends State<WeekViewPager>
with AutomaticKeepAliveClientMixin {
int lastMonth; // int lastMonth; //
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
@ -22,6 +22,7 @@ class _WeekViewPagerState extends State<WeekViewPager> {
@override @override
void initState() { void initState() {
super.initState();
LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager initState"); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager initState");
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
@ -37,6 +38,7 @@ class _WeekViewPagerState extends State<WeekViewPager> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager build"); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager build");
// CalendarProvider,listenfalse // CalendarProvider,listenfalse
@ -52,19 +54,25 @@ class _WeekViewPagerState extends State<WeekViewPager> {
if (calendarProvider.expandStatus.value == true) { if (calendarProvider.expandStatus.value == true) {
return; return;
} }
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: "WeekViewPager PageView onPageChanged:${position}"); message:
// "WeekViewPager PageView onPageChanged,position:$position");
DateModel firstDayOfWeek = configuration.weekList[position]; DateModel firstDayOfWeek = configuration.weekList[position];
int currentMonth = firstDayOfWeek.month; int currentMonth = firstDayOfWeek.month;
//
configuration.weekChangeListeners.forEach((listener) {
listener(firstDayOfWeek.year, firstDayOfWeek.month);
});
if (lastMonth != currentMonth) { if (lastMonth != currentMonth) {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: message:
"WeekViewPager PageView monthChange:currentMonth:${currentMonth}"); "WeekViewPager PageView monthChange:currentMonth:$currentMonth");
configuration.monthChange( configuration.monthChangeListeners.forEach((listener) {
firstDayOfWeek.year, firstDayOfWeek.month); listener(firstDayOfWeek.year, firstDayOfWeek.month);
});
lastMonth = currentMonth; lastMonth = currentMonth;
if (calendarProvider.lastClickDateModel == null || if (calendarProvider.lastClickDateModel == null ||
calendarProvider.lastClickDateModel.month != currentMonth) { calendarProvider.lastClickDateModel.month != currentMonth) {
@ -92,4 +100,7 @@ class _WeekViewPagerState extends State<WeekViewPager> {
), ),
); );
} }
@override
bool get wantKeepAlive => true;
} }

@ -1,6 +1,20 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: packages:
archive:
dependency: transitive
description:
name: archive
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.10"
args:
dependency: transitive
description:
name: args
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.2"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -29,6 +43,20 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.14.11" version: "1.14.11"
convert:
dependency: transitive
description:
name: convert
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
description: flutter description: flutter
@ -39,6 +67,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -59,7 +94,7 @@ packages:
name: path name: path
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.6.2" version: "1.6.4"
pedantic: pedantic:
dependency: transitive dependency: transitive
description: description:
@ -67,20 +102,27 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.8.0+1" version: "1.8.0+1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.0"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
name: provider name: provider
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.0+1" version: "3.1.0+1"
quiver: quiver:
dependency: transitive dependency: transitive
description: description:
name: quiver name: quiver
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.3" version: "2.0.5"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@ -113,7 +155,7 @@ packages:
name: string_scanner name: string_scanner
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.0.4" version: "1.0.5"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
@ -142,5 +184,12 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.8" version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.5.0"
sdks: sdks:
dart: ">=2.2.2 <3.0.0" dart: ">=2.4.0 <3.0.0"

@ -10,7 +10,7 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
provider: 3.0.0+1 provider: ^3.1.0+1
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter

Loading…
Cancel
Save