|
| 1 | +# mini_calendar |
| 2 | + |
| 3 | +Date component developed with Flutter, plans to support display, swipe left and right, add date mark, radio, display week, etc. |
| 4 | + |
| 5 | +使用Flutter开发的日期组件,计划支持显示,左右滑动,添加日期标记,单选,显示星期等功能。 |
| 6 | + |
| 7 | + |
| 8 | +<a name="sVRq8"></a> |
| 9 | +## 开发日记 |
| 10 | +<a name="ria82"></a> |
| 11 | +### 2019-12-09 记 |
| 12 | +> 主要想实现的内容 |
| 13 | +
|
| 14 | + |
| 15 | + |
| 16 | +<a name="mini_calendar"></a> |
| 17 | +### 2019-12-10 记 |
| 18 | +> 整体上,从简单的显示开始,然后再加入交互和控制功能。第一版显示方面,先考虑实现最常用的月视图。 |
| 19 | +
|
| 20 | +<a name="ahzoY"></a> |
| 21 | +#### 月视图实现 |
| 22 | +> 日历的月视图,是非常规则的表格形式。所以就考虑用GridView来实现。 |
| 23 | +
|
| 24 | +1. 写两个类,来管理月和日,并重构了比较运算符。 |
| 25 | + |
| 26 | +```dart |
| 27 | +/// 月 |
| 28 | +class DateMonth { |
| 29 | + int year; |
| 30 | + int month; |
| 31 | + int maxDays; |
| 32 | + // …… |
| 33 | +} |
| 34 | +
|
| 35 | +/// 日 |
| 36 | +class DateDay extends DateMonth{ |
| 37 | + int day; |
| 38 | + // …… |
| 39 | +} |
| 40 | +
|
| 41 | +
|
| 42 | +``` |
| 43 | + |
| 44 | +2. 在写月视图时,需要考虑开始星期所在位置,非当月日期的显示情况等。这里的关键在于计算位置。 |
| 45 | + |
| 46 | + |
| 47 | + |
| 48 | +<a name="mXiJH"></a> |
| 49 | +### 2019-12-12 记 |
| 50 | +> 由于GridView在控制高度上面有所不便(可能有好多方法,我没有尝试到),我换成了Warp的方式来实现。 |
| 51 | +
|
| 52 | +<a name="wa1Sw"></a> |
| 53 | +#### 切换月份 |
| 54 | +> 常见的月份切换方式,有类似小米的左右滑动切换,也有上下滑动切换。第一个想到的就是用PageView来实现该功能。 |
| 55 | +
|
| 56 | +问题:如何实现无限切换? |
| 57 | + |
| 58 | +1. 构建前,全部加载完成,然后就可以随意切换了。否决,不够灵活,性能开销大。 |
| 59 | +1. 动态分配,初始化3页,然后监听滑动,动态首尾动态添加对应月份。可以考虑,但跨度大了,数据会不断膨胀,可以再优化下。 |
| 60 | +1. 动态分配,动态移除,设定缓存大小,超出缓存范围的将被移除。可以,那就按照这个方案进行! |
| 61 | + |
| 62 | +问题:如何实现动态分配? |
| 63 | +> 原理如下,先动态分配数据,然后跳转到指定页面。若考虑缓存机制,可在remove前加判断即可。 |
| 64 | +
|
| 65 | + |
| 66 | + |
| 67 | +> 下面是核心代码 |
| 68 | +
|
| 69 | + |
| 70 | +```dart |
| 71 | +List<int> pages = [-1, 0, 1]; |
| 72 | +PageController _controller = PageController(initialPage: 1); |
| 73 | +_controller.addListener(() { |
| 74 | + double position = _controller.position.pixels; |
| 75 | + if (position == 0) { |
| 76 | + pages.insert(0, pages.first - 1); |
| 77 | + pages.remove(pages.last); |
| 78 | + _controller.jumpToPage(1); |
| 79 | + } else if (position == _controller.position.maxScrollExtent) { |
| 80 | + pages.add(pages.last + 1); |
| 81 | + pages.remove(pages.first); |
| 82 | + _controller.jumpToPage(1); |
| 83 | + } else { |
| 84 | + return; |
| 85 | + } |
| 86 | + setState((){}); |
| 87 | +}); |
| 88 | +``` |
| 89 | +有了上面的基础,切换月份,也就变成一件简单的事情了。 |
| 90 | +<a name="apfsx"></a> |
| 91 | +### 2019-12-14 记 |
| 92 | +<a name="7iLxK"></a> |
| 93 | +#### 实现简单日历 |
| 94 | + |
| 95 | +<a name="mfYMK"></a> |
| 96 | +#### 连选实现 |
| 97 | +> 主要是处理日期选中后的赋值问题。 |
| 98 | +
|
| 99 | +当下的处理逻辑有很多,我这里采用的是以下逻辑: |
| 100 | + |
| 101 | +1. 单选和连选只同时支持一种(理论上可以同时支持,后续可以再优化实现) |
| 102 | +1. 第一次选择日期,给到开始日期上。 |
| 103 | +1. 第二次选择日期,将小日期给到开始日期,大日期给到结束日期上。 |
| 104 | +1. 第三次选择日期,当落在小、大之间时,更换大日期。当不落在之间时,小、大日期全部清空。相当于取消选择。 |
| 105 | + |
| 106 | +<a name="IppLr"></a> |
| 107 | +### 2019-12-15 记 |
| 108 | +<a name="Z2pEK"></a> |
| 109 | +#### 实现可单选、连选、左右滑动日历控件 |
| 110 | + |
| 111 | +- 月视图添加背景 |
| 112 | +- 可自定义起始星期 |
| 113 | +- 可自定义实现周头部控件 |
| 114 | +- 可自定义实现标记组件 |
| 115 | +- 利用[切换月份](#%E5%88%87%E6%8D%A2%E6%9C%88%E4%BB%BD)和[连选实现](#%E8%BF%9E%E9%80%89%E5%AE%9E%E7%8E%B0)完成左右切换的可单选、连选的日期控件 |
| 116 | + |
| 117 | +   |
| 118 | + |
0 commit comments