Flutter定时器控制插件timer_controller的使用
Flutter定时器控制插件timer_controller的使用
概述
timer_controller
是一个Flutter库,它提供了对计时器的操作(播放、暂停、重启等)以及用于消费计时器值的小部件。这个库非常适合需要在应用中实现倒计时或正计时功能的开发者。
开始使用
添加依赖
在你的 pubspec.yaml
文件中添加以下依赖:
dependencies:
...
timer_controller: ^0.1.0
然后在 Dart 文件中导入包:
import 'package:timer_controller/timer_controller.dart';
TimerController
TimerController
继承自 ValueNotifier
,因此你可以访问它的 value
属性来获取计时器的信息。
构造函数
根据可用的时间单位,可以使用不同的构造函数创建 TimerController
实例:
final TimerController secondsTimer = TimerController.seconds(15);
final TimerController minutesTimer = TimerController.minutes(3);
final TimerController hoursTimer = TimerController.hours(2);
注意:记得在不再需要 TimerController
时调用 dispose()
方法释放资源。
控制方法
start()
:开始计时。pause()
:暂停计时。reset()
:将计时器重置为初始值。restart()
:将计时器重置为初始值并重新开始计时。
TimerValue
TimerValue
表示计时器的状态,并具有以下属性:
TimerValue({
required int remaining, // 剩余时间
required TimerUnit unit, // 计时单位
TimerStatus status = TimerStatus.initial, // 计时器状态
});
内置小部件
timer_controller
提供了几个内置的小部件来构建基于控制器的UI或执行某些动作。
TimerControllerBuilder
TimerControllerBuilder
可以根据 TimerController
的值构建小部件:
TimerControllerBuilder(
controller: myTimerController,
builder: (context, value, child) {
// 根据 myTimerController 的值返回相应的 widget
}
)
可选条件:如果想要更细粒度地控制何时调用构建函数,可以提供一个条件给 TimerControllerBuilder
。该条件接受前一个计时器值和当前计时器值作为参数,并返回一个布尔值。如果条件返回 true
,则构建函数将被调用,并且小部件会重新构建;如果条件返回 false
,则不会调用构建函数也不会触发重建。
TimerControllerListener
TimerControllerListener
可以根据 TimerController
的值运行特定的动作:
TimerControllerListener(
controller: myTimerController,
listener: (context, value) {
// 根据 myTimerController 的值执行相应操作
},
child: Container(),
)
可选条件:与 TimerControllerBuilder
类似,可以通过提供条件来控制监听器函数的调用时机。
示例代码
下面是一个完整的示例程序,展示了如何使用 timer_controller
创建一个简单的计时器应用程序:
import 'package:flutter/material.dart';
import 'package:timer_controller/timer_controller.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Timer controller demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const _TimerWidget(),
);
}
}
class _TimerWidget extends StatefulWidget {
const _TimerWidget({Key? key}) : super(key: key);
@override
__TimerWidgetState createState() => __TimerWidgetState();
}
class __TimerWidgetState extends State<_TimerWidget> {
late TimerController _controller;
@override
void initState() {
_controller = TimerController.seconds(20);
super.initState();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Timer controller demo'),
),
body: TimerControllerListener(
controller: _controller,
listenWhen: (previousValue, currentValue) =>
previousValue.status != currentValue.status,
listener: (context, timerValue) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Status: ${describeEnum(timerValue.status)}'),
duration: const Duration(seconds: 1),
),
);
},
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TimerControllerBuilder(
controller: _controller,
builder: (context, timerValue, _) {
Color timerColor = Colors.black;
switch (timerValue.status) {
case TimerStatus.initial:
timerColor = Colors.black;
break;
case TimerStatus.running:
timerColor = Colors.green;
break;
case TimerStatus.paused:
timerColor = Colors.grey;
break;
case TimerStatus.finished:
timerColor = Colors.red;
break;
}
return Text(
'${timerValue.remaining}',
style: TextStyle(
fontSize: 50,
color: timerColor,
),
);
},
),
const SizedBox(height: 40),
Wrap(
spacing: 20,
runSpacing: 20,
children: [
_ActionButton(
title: 'Start',
onPressed: () => _controller.start(),
),
_ActionButton(
title: 'Pause',
onPressed: () => _controller.pause(),
),
_ActionButton(
title: 'Reset',
onPressed: () => _controller.reset(),
),
_ActionButton(
title: 'Restart',
onPressed: () => _controller.restart(),
),
],
),
],
),
),
),
);
}
}
class _ActionButton extends StatelessWidget {
const _ActionButton({
Key? key,
this.onPressed,
required this.title,
}) : assert(title != null),
super(key: key);
final VoidCallback? onPressed;
final String title;
@override
Widget build(BuildContext context) {
return OutlinedButton(
onPressed: onPressed,
child: Text(title),
);
}
}
这段代码创建了一个包含计时器显示和四个按钮(开始、暂停、重置、重启)的应用程序界面。当计时器状态改变时,还会显示一个短暂的消息提示用户当前的状态。
更多关于Flutter定时器控制插件timer_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter定时器控制插件timer_controller的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何在Flutter中使用timer_controller
插件来控制定时器的代码示例。timer_controller
是一个假定的插件名称,因为实际上Flutter生态系统中没有一个广泛认可的名为timer_controller
的插件。不过,我们可以模拟一个类似的定时器控制逻辑,通常可以通过TickerProviderStateMixin
和AnimationController
来实现类似的功能。
为了演示,我们将创建一个简单的Flutter应用,其中包含一个按钮,点击按钮后开始一个定时器,并在屏幕上显示经过的时间。我们还将提供一个停止按钮来停止定时器。
首先,确保你的pubspec.yaml
文件中包含了必要的依赖项(虽然本例不直接依赖外部插件,但Flutter开发通常需要flutter
依赖):
dependencies:
flutter:
sdk: flutter
接下来,在你的main.dart
文件中编写以下代码:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Timer Controller Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: TimerScreen(),
);
}
}
class TimerScreen extends StatefulWidget {
@override
_TimerScreenState createState() => _TimerScreenState();
}
class _TimerScreenState extends State<TimerScreen> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<int> _animation;
int _elapsedTime = 0;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(days: 1), // Long duration to simulate indefinite running
vsync: this,
)..repeat(reverse: false); // We won't actually use the animation's value for timing
// Create an animation that updates every second (or any desired interval)
_animation = IntTween(begin: 0, end: _controller.value.toInt() * 1000) // Dummy end value
.animate(CurvedAnimation(
parent: _controller,
curve: Curves.linear,
))
..addListener(() {
setState(() {
// Here we manually update the elapsed time (not using _animation.value directly)
_elapsedTime = DateTime.now().difference(_startTime).inSeconds;
});
});
// Start time for elapsed time calculation
DateTime _startTime = DateTime.now();
// We will use a Timer to update our state instead of relying on _animation.value
Timer.periodic(Duration(seconds: 1), (timer) {
setState(() {
_elapsedTime = DateTime.now().difference(_startTime).inSeconds;
});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _startTimer() {
// In this demo, the timer starts immediately in initState, so this function is a no-op.
// You can modify this to reset and restart the timer if needed.
}
void _stopTimer() {
_controller.stop();
// Optionally, you can reset the timer here if needed: _controller.reset();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Timer Controller Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Elapsed Time: $_elapsedTime seconds',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _startTimer, // In this demo, just a placeholder
child: Text('Start Timer'),
),
SizedBox(height: 10),
ElevatedButton(
onPressed: _stopTimer,
child: Text('Stop Timer'),
),
],
),
),
);
}
}
注意:
- 在这个示例中,我们实际上并没有直接使用
AnimationController
来控制定时器的显示(因为我们手动计算了经过的时间),但展示了如何结合TickerProviderStateMixin
和AnimationController
的初始化流程。 - 为了模拟定时器的功能,我们使用了一个
Timer.periodic
来每秒更新一次UI。 _startTimer
函数在这个示例中没有实际作用,因为定时器在initState
中就已经开始。你可以根据需求修改这部分逻辑,比如重置和重新开始定时器。- 停止定时器时,我们调用了
_controller.stop()
,但实际上并没有用到_controller
的动画值。在实际应用中,你可能需要根据具体需求调整这部分逻辑。
这个示例提供了一个基础框架,你可以根据自己的需求进一步扩展和优化。