
2.5 开发番茄钟
本节将开发一个简单的番茄钟计时器,以巩固本章介绍的理论基础。
lib/main.dart是App的入口页面,因此需要对默认代码进行重写。首先创建番茄钟的首页MyHomePage,它是带有状态的StatefulWidget,状态类为_MyHomePageState。在build方法中进行布局搭建,使用Scaffold组件搭建页面的骨架。在Scaffold中,body表示页面的内容区,这里通过Text组件展示了一段文本,并通过floatingActionButton属性添加了一个悬浮按钮。将main.dart的代码替换如下:


运行代码效果如图2-5所示。
其中,界面中包含一个展示文本和一个悬浮按钮。目前应用还不具备实际功能,将在下面小节中逐步进行实现。
2.5.1 使用Center组件进行居中显示
在上面的代码中,向Scaffold组件的body传入了一个Center组件,其作用是在视图容器中居中显示。
如果不使用Center组件,而是直接向Scaffold传入Text组件,运行程序会发现文本定位到了起始位置,即屏幕的左上角,如图2-6所示。


图2-5 番茄钟初始界面效果

图2-6 未使用Center组件时文本展示效果
2.5.2 Text文本展示组件
番茄钟的主要功能是25 min倒计时,首先需要在屏幕上创建一个文本展示组件,来展示倒计时。在Flutter中,展示文本使用Text组件。

图2-7 文本组件展示效果
下面代码创建了一个文本,其运行效果如图2-7所示。

需要注意的是,Text组件需要被嵌套在Scaffold组件内部使用,如果跳过Scaffold直接使用Text,由于默认样式没有设置,会出现展示异常的效果,如图2-8所示。

图2-8 Text在Scaffold外的异常展示效果
通过Text的style属性可以方便地设置文本样式。下面介绍一些基础的样式设置方法。
1 设置文本颜色
通过TextStyle样式的color属性可以修改文本颜色,示例代码如下:

运行效果如图2-9所示。

图2-9 设置文本颜色效果
2 设置字体大小
通过TextStyle样式的fontSize属性可以修改文本大小,示例代码如下:

运行效果如图2-10所示。
3 文字加粗
通过TextStyle样式的fontWeight属性可以修改文本颜色,示例代码如下:

运行效果如图2-11所示。

图2-10 设置字体大小效果

图2-11 字体加粗效果
4 倒计时文本组件
了解了Text组件的基础使用后,下面回到番茄钟工程,创建倒计时文本展示组件。将main.dart位于屏幕中心的Text替换为以下代码:

其中设定了一个固定文本,在下一节对定时器的讲解中,会通过状态对其进行替换。再次运行main.dart效果如图2-12所示。

图2-12 倒计时文本组件展示效果
2.5.3 添加Timer定时器
在应用开发中经常会使用到定时器,它能够每隔一段时间触发执行相应代码。一种典型的应用场景是网络轮询请求,每隔固定时间发起请求,适用于一些需要定时与后端数据保持同步的应用场景。
Dart标准库的async包中提供了定时器能力,具体实现类为Timer。
Timer的使用主要分为几个步骤,首先在组件的初始化生命周期中创建一个Timer实例,在创建时需指定定时间隔(Duration),以及定时触发时所需执行的代码。
Timer有两种工作模式:单次触发与循环触发。
对于单次触发,定时器触发一次后自动停止。创建方法如下:

其中,通过debugPrint方法可以输出日志。
对于循环触发,定时器会循环定时触发下去,直到调用它的cancel()方法手动停止。创建方法如下:

结合番茄钟实例,基于周期为1s的定时器,创建一个状态用于统计倒计时的秒数。具体代码如下:

运行程序可以看到Logcat日志:

2.5.4 为按钮添加单击事件控制番茄钟开始
现在文本展示、按钮及定时器都已就绪,接下来需要将它们串起来。FloatingActionButton的onPress属性用于设置按钮单击后的行为,这也是整个程序的触发点。当单击按钮后,创建定时器开始计时,每次定时器触发时都更新countDownSeconds状态,每次状态变化倒计时文本组件也会进行相应更新。如果定时器倒计时为0,还需要再关闭定时器,同时弹出一个对话框向用户发出提示。具体实现代码如下:


其中,将startCountDown设置为悬浮按钮的回调函数,在其中启动定时器。通过showDialog方法弹出对话框。parseText方法用于将countDown状态从整数转换为文本形式进行展示。pad-Digits方法的作用是将只有一位的整数通过补0将其扩充至两位,使其更加美观。
运行程序,倒计时中效果如图2-13所示,倒计时完成后弹窗提示如图2-14所示。

图2-13 番茄钟运行时效果

图2-14 倒计时结束弹窗提示