案例介绍
起初我们来到这个世界, 是因为我们不得不来, 最后我们离开这个世界, 是因为我们不得不走. 出生和死亡都是我们没有把握的事情, 但是我们能把握的是从出生到死亡这段时间. 中国目前的人均寿命是 76.25
年, 算上程序员通宵透支的生命, 大约是 75
年, 也就是 30 * 30
个月. 本案例是用 Flutter
记录并计算生命的剩余时间:
项目地址: https://github.com/zhouzaihang/life_countdown
实现思路
- 页面分为三块, 第一部分显示时间, 第二部分显示时间格子, 第三部分显示剩余天数
- 在第一部分右边设置一个按钮, 点击时弹出时间选择器更改出生时间
代码
完成的代码见 Github
life.dart
首先新建 life.dart
, 编写第一个类 Life
. 这个类主要有三个功能:
根据生日自动和当前时间计算逝去的生命和剩余的岁月
使用
SharedPreferences
存储数据到本地, 方便下次打开应用的时候自动从本地读取数据使用
ScopedModel
作为状态管理, 在生日修改后, 更新所有相关的组件
1 | import 'package:scoped_model/scoped_model.dart'; |
构建首页
首先分析下首页的页面可以使用 Material
的 Scaffold
脚手架组件构建, 第一部分使用 APPBar
, 第二三部分作为 body
部分. 另外在上面构建life
类的时候, 用到了 ScopedModel
进行状态管理. 所以这里在所有组件的根节点上先创一个 ScopedModel
组件, 使得后面的所有组件都能够直接通过 model
内的 life
对象且, 当对应内容修改时, 能够自动更新视图. 关于状态管理组件 ScopedModel
介绍参考这篇文章 ScopedModel 和官方文档.
具体实现代码如下:
1 | import 'package:flutter/material.dart'; |
构建 AppBar
第一部分主要是一个居中的日期和一个按钮:
1 | appBar: AppBar( |
这里的字体是自定义的, Flutter
使用自定义字体的方法:
- 将文件放在项目目录下, 例如项目的
asset
下:
- 在
pubspec.yaml
下编写资源名字和相对路径:
1 | flutter: |
- 在相应的地方使用
fontFamily
调用:
1 | Text( |
添加时间选择器
第一部分右边的按钮是可以弹出时间选择器进行生日设置并保存且更新视图, Flutter
内置了时间选择器, 可以使用 showDatePicker
构建, 完整代码如下:
1 | void showDefaultYearPicker(BuildContext context, Life life) async { |
构建 body
Body
由第二部分: 一个网格和第三部分: 一个表示剩余时间的 Text
组件.
网格组件
新建 grid.dart
文件, 然后创建一个有状态组件 Grid
, 把 life
作为传入组件的必要参数:
1 | import 'dart:math'; |
设置一个 List
用于存放网格的随机颜色:
1 | static List<int> colors = [ |
网格是由一个一个小格子组成, 这里使用 Border
组件实现. 还需要定义一个根据对应的位置生成 Border
的方法:
1 | static BorderSide _borderThin = |
网格可以看成是由 30
行组成, 每一行有 30
个 border
组件, 先定义生成一行的方法:
1 | List<Widget> rowDetail(rowIndex) { |
再定义生成所有行的代码:
1 | List<Widget> rowList() { |
最后把生成的所有行使用 Column
组件包起来就OK了, 最后完整的 grid.dart
如下:
1 | import 'dart:math'; |
然后在 main.dart
里引用 grid.dart
代码, 并在调用 Text
组件实现第三部分功能:
1 | ScopedModelDescendant<Life>( |
最后完整的 main.dart
文件的内容如下:
1 | import 'package:flutter/material.dart'; |