[英]Flutter Countdown Timer
How can I do to put the value passed in the construction, to make a timer that rounds to the first decimal and shows at the child text of my RaisedButton?如何将传递的值放入构造中,制作一个四舍五入到第一个小数点并显示在我的 RaisedButton 的子文本中的计时器? I've tried but without luck.我试过但没有运气。 I manage to make work the callback function with a simple Timer but no periodic and with no update of value in real time in the text...我设法使用一个简单的 Timer 使回调函数工作,但没有周期性,也没有在文本中实时更新值......
import 'package:flutter/material.dart';
import 'dart:ui';
import 'dart:async';
class TimerButton extends StatefulWidget {
final Duration timerTastoPremuto;
TimerButton(this.timerTastoPremuto);
@override
_TimerButtonState createState() => _TimerButtonState();
}
class _TimerButtonState extends State<TimerButton> {
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(5.0),
height: 135.0,
width: 135.0,
child: new RaisedButton(
elevation: 100.0,
color: Colors.white.withOpacity(.8),
highlightElevation: 0.0,
onPressed: () {
int _start = widget.timerTastoPremuto.inMilliseconds;
const oneDecimal = const Duration(milliseconds: 100);
Timer _timer = new Timer.periodic(
oneDecimal,
(Timer timer) =>
setState(() {
if (_start < 100) {
_timer.cancel();
} else {
_start = _start - 100;
}
}));
},
splashColor: Colors.red,
highlightColor: Colors.red,
//shape: RoundedRectangleBorder e tutto il resto uguale
shape: BeveledRectangleBorder(
side: BorderSide(color: Colors.black, width: 2.5),
borderRadius: new BorderRadius.circular(15.0)),
child: new Text(
"$_start",
style: new TextStyle(fontFamily: "Minim", fontSize: 50.0),
),
),
);
}
}
Here is an example using Timer.periodic :这是一个使用Timer.periodic的示例:
Countdown starts from 10
to 0
on button click :倒计时从10
到0
按钮单击开始:
import 'dart:async';
[...]
Timer _timer;
int _start = 10;
void startTimer() {
const oneSec = const Duration(seconds: 1);
_timer = new Timer.periodic(
oneSec,
(Timer timer) {
if (_start == 0) {
setState(() {
timer.cancel();
});
} else {
setState(() {
_start--;
});
}
},
);
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text("Timer test")),
body: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
startTimer();
},
child: Text("start"),
),
Text("$_start")
],
),
);
}
Result :结果 :
You can also use the CountdownTimer class from the quiver.async library, usage is even simpler :您还可以使用quiver.async库中的CountdownTimer类,使用更加简单:
import 'package:quiver/async.dart';
[...]
int _start = 10;
int _current = 10;
void startTimer() {
CountdownTimer countDownTimer = new CountdownTimer(
new Duration(seconds: _start),
new Duration(seconds: 1),
);
var sub = countDownTimer.listen(null);
sub.onData((duration) {
setState(() { _current = _start - duration.elapsed.inSeconds; });
});
sub.onDone(() {
print("Done");
sub.cancel();
});
}
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: Text("Timer test")),
body: Column(
children: <Widget>[
RaisedButton(
onPressed: () {
startTimer();
},
child: Text("start"),
),
Text("$_current")
],
),
);
}
EDIT : For the question in comments about button click behavior编辑:关于按钮点击行为的评论中的问题
With the above code which uses Timer.periodic
, a new timer will indeed be started on each button click, and all these timers will update the same _start
variable, resulting in a faster decreasing counter.使用上面使用Timer.periodic
的代码,每次单击按钮时都会启动一个新的计时器,并且所有这些计时器将更新相同的_start
变量,从而导致更快的递减计数器。
There are multiple solutions to change this behavior, depending on what you want to achieve :有多种解决方案可以改变这种行为,具体取决于您想要实现的目标:
Timer.periodic
creation with a non null condition so that clicking the button multiple times has no effect用非空条件包装Timer.periodic
创建,以便多次单击按钮无效if (_timer != null) {
_timer = new Timer.periodic(...);
}
if (_timer != null) {
_timer.cancel();
_start = 10;
}
_timer = new Timer.periodic(...);
if (_timer != null) {
_timer.cancel();
_timer = null;
} else {
_timer = new Timer.periodic(...);
}
You could also use this official async package which provides a RestartableTimer class which extends from Timer
and adds the reset
method.你也可以使用这个官方的异步包,它提供了一个从Timer
扩展的RestartableTimer类并添加了reset
方法。
So just call _timer.reset();
所以只需调用_timer.reset();
on each button click.在每个按钮点击。
Finally, Codepen now supports Flutter !最后,Codepen 现在支持 Flutter! So here is a live example so that everyone can play with it : https://codepen.io/Yann39/pen/oNjrVOb所以这里是一个活生生的例子,这样每个人都可以玩它: https ://codepen.io/Yann39/pen/oNjrVOb
I have created a Generic Timer Widget which can be used to display any kind of timer and its flexible as well.我创建了一个通用计时器小部件,它可以用来显示任何类型的计时器,而且它也很灵活。
This Widget takes following properties此小部件具有以下属性
hh mm ss
string like 01 hours: 20 minutes: 45 seconds
countDownFormatter :用户想要显示倒数计时器的方式,例如hh mm ss
字符串,如01 hours: 20 minutes: 45 seconds
you can provide a default formatter ( formatHHMMSS
) in case you don't want to supply it from every place.您可以提供一个默认格式化程序 ( formatHHMMSS
),以防您不想从每个地方提供它。
// provide implementation for this - formatHHMMSS(duration.inSeconds);
// 为此提供实现 - formatHHMMSS(duration.inSeconds);
or use below one which I have provided.或使用我提供的以下一个。
import 'package:flutter/material.dart';
class CountDownTimer extends StatefulWidget {
const CountDownTimer({
Key key,
int secondsRemaining,
this.countDownTimerStyle,
this.whenTimeExpires,
this.countDownFormatter,
}) : secondsRemaining = secondsRemaining,
super(key: key);
final int secondsRemaining;
final Function whenTimeExpires;
final Function countDownFormatter;
final TextStyle countDownTimerStyle;
State createState() => new _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
AnimationController _controller;
Duration duration;
String get timerDisplayString {
Duration duration = _controller.duration * _controller.value;
return widget.countDownFormatter != null
? widget.countDownFormatter(duration.inSeconds)
: formatHHMMSS(duration.inSeconds);
// In case user doesn't provide formatter use the default one
// for that create a method which will be called formatHHMMSS or whatever you like
}
@override
void initState() {
super.initState();
duration = new Duration(seconds: widget.secondsRemaining);
_controller = new AnimationController(
vsync: this,
duration: duration,
);
_controller.reverse(from: widget.secondsRemaining.toDouble());
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed || status == AnimationStatus.dismissed) {
widget.whenTimeExpires();
}
});
}
@override
void didUpdateWidget(CountDownTimer oldWidget) {
if (widget.secondsRemaining != oldWidget.secondsRemaining) {
setState(() {
duration = new Duration(seconds: widget.secondsRemaining);
_controller.dispose();
_controller = new AnimationController(
vsync: this,
duration: duration,
);
_controller.reverse(from: widget.secondsRemaining.toDouble());
_controller.addStatusListener((status) {
if (status == AnimationStatus.completed) {
widget.whenTimeExpires();
} else if (status == AnimationStatus.dismissed) {
print("Animation Complete");
}
});
});
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Center(
child: AnimatedBuilder(
animation: _controller,
builder: (_, Widget child) {
return Text(
timerDisplayString,
style: widget.countDownTimerStyle,
);
}));
}
}
Usage:用法:
Container(
width: 60.0,
padding: EdgeInsets.only(top: 3.0, right: 4.0),
child: CountDownTimer(
secondsRemaining: 30,
whenTimeExpires: () {
setState(() {
hasTimerStopped = true;
});
},
countDownTimerStyle: TextStyle(
color: Color(0XFFf5a623),
fontSize: 17.0,
height: 1.2,
),
),
)
example for formatHHMMSS :格式HHMMSS示例:
String formatHHMMSS(int seconds) {
int hours = (seconds / 3600).truncate();
seconds = (seconds % 3600).truncate();
int minutes = (seconds / 60).truncate();
String hoursStr = (hours).toString().padLeft(2, '0');
String minutesStr = (minutes).toString().padLeft(2, '0');
String secondsStr = (seconds % 60).toString().padLeft(2, '0');
if (hours == 0) {
return "$minutesStr:$secondsStr";
}
return "$hoursStr:$minutesStr:$secondsStr";
}
Null Safe Version of the Above Code上述代码的空安全版本
import 'package:flutter/material.dart';
class CountDownTimer extends StatefulWidget {
const CountDownTimer({
Key? key,
required this.secondsRemaining,
required this.whenTimeExpires,
this.countDownFormatter,
this.countDownTimerStyle,
}) : super(key: key);
final int secondsRemaining;
final VoidCallback whenTimeExpires;
final TextStyle? countDownTimerStyle;
final Function(int seconds)? countDownFormatter;
@override
State createState() => _CountDownTimerState();
}
class _CountDownTimerState extends State<CountDownTimer>
with TickerProviderStateMixin {
late final AnimationController _controller;
late final Duration duration;
String get timerDisplayString {
final duration = _controller.duration! * _controller.value;
if (widget.countDownFormatter != null) {
return widget.countDownFormatter!(duration.inSeconds) as String;
} else {
return formatHHMMSS(duration.inSeconds);
}
}
String formatHHMMSS(int seconds) {
final hours = (seconds / 3600).truncate();
seconds = (seconds % 3600).truncate();
final minutes = (seconds / 60).truncate();
final hoursStr = (hours).toString().padLeft(2, '0');
final minutesStr = (minutes).toString().padLeft(2, '0');
final secondsStr = (seconds % 60).toString().padLeft(2, '0');
if (hours == 0) {
return '$minutesStr:$secondsStr';
}
return '$hoursStr:$minutesStr:$secondsStr';
}
@override
void initState() {
super.initState();
duration = Duration(seconds: widget.secondsRemaining);
_controller = AnimationController(
vsync: this,
duration: duration,
);
_controller
..reverse(from: widget.secondsRemaining.toDouble())
..addStatusListener((status) {
if (status == AnimationStatus.completed ||
status == AnimationStatus.dismissed) {
widget.whenTimeExpires();
}
});
}
@override
void didUpdateWidget(CountDownTimer oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.secondsRemaining != oldWidget.secondsRemaining) {
setState(() {
duration = Duration(seconds: widget.secondsRemaining);
_controller.dispose();
_controller = AnimationController(
vsync: this,
duration: duration,
);
_controller
..reverse(from: widget.secondsRemaining.toDouble())
..addStatusListener((status) {
if (status == AnimationStatus.completed) {
widget.whenTimeExpires();
}
});
});
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _controller,
builder: (_, Widget? child) {
return Text(
timerDisplayString,
style: widget.countDownTimerStyle,
);
},
),
);
}
}
Little late to the party but why don't you guys try animation.No I am not telling you to manage animation controllers and disposing them off and all that stuff, there's a built-in widget for that called TweenAnimationBuilder .派对迟到了,但你们为什么不尝试动画。不,我不是在告诉你管理动画控制器并将它们处理掉以及所有这些东西,有一个名为TweenAnimationBuilder的内置小部件。 You can animate between values of any type, here's an example with a Duration class您可以在任何类型的值之间进行动画处理,这是一个 Duration 类的示例
TweenAnimationBuilder<Duration>(
duration: Duration(minutes: 3),
tween: Tween(begin: Duration(minutes: 3), end: Duration.zero),
onEnd: () {
print('Timer ended');
},
builder: (BuildContext context, Duration value, Widget? child) {
final minutes = value.inMinutes;
final seconds = value.inSeconds % 60;
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Text('$minutes:$seconds',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
fontSize: 30)));
}),
and You also get onEnd call back which notifies you when the animation completes;并且您还会收到 onEnd 回调,它会在动画完成时通知您;
here's the output这是输出
Here is my Timer widget, not related to the Question but may help someone.这是我的计时器小部件,与问题无关,但可能对某人有所帮助。
import 'dart:async';
import 'package:flutter/material.dart';
class OtpTimer extends StatefulWidget {
@override
_OtpTimerState createState() => _OtpTimerState();
}
class _OtpTimerState extends State<OtpTimer> {
final interval = const Duration(seconds: 1);
final int timerMaxSeconds = 60;
int currentSeconds = 0;
String get timerText =>
'${((timerMaxSeconds - currentSeconds) ~/ 60).toString().padLeft(2, '0')}: ${((timerMaxSeconds - currentSeconds) % 60).toString().padLeft(2, '0')}';
startTimeout([int milliseconds]) {
var duration = interval;
Timer.periodic(duration, (timer) {
setState(() {
print(timer.tick);
currentSeconds = timer.tick;
if (timer.tick >= timerMaxSeconds) timer.cancel();
});
});
}
@override
void initState() {
startTimeout();
super.initState();
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.timer),
SizedBox(
width: 5,
),
Text(timerText)
],
);
}
}
You will get something like this你会得到这样的东西
doesnt directly answer your question.不直接回答你的问题。 But helpful for those who want to start something after some time.但对那些想在一段时间后开始做某事的人很有帮助。
Future.delayed(Duration(seconds: 1), () {
print('yo hey');
});
If all you need is a simple countdown timer, this is a good alternative instead of installing a package.如果您只需要一个简单的倒数计时器,那么这是一个不错的选择,而不是安装软件包。 Happy coding!快乐编码!
countDownTimer() async {
int timerCount;
for (int x = 5; x > 0; x--) {
await Future.delayed(Duration(seconds: 1)).then((_) {
setState(() {
timerCount -= 1;
});
});
}
}
I'm using https://pub.dev/packages/flutter_countdown_timer我正在使用https://pub.dev/packages/flutter_countdown_timer
dependencies: flutter_countdown_timer: ^1.0.0依赖项:flutter_countdown_timer:^1.0.0
$ flutter pub get $颤振酒吧得到
CountdownTimer(endTime: 1594829147719)
1594829147719 is your timestamp in milliseconds 1594829147719 是您的时间戳,以毫秒为单位
import 'dart:async';
import 'package:flutter/material.dart';
class CustomTimer extends StatefulWidget {
@override
_CustomTimerState createState() => _CustomTimerState();
}
class _CustomTimerState extends State<CustomTimer> {
final _maxSeconds = 61;
int _currentSecond = 0;
Timer _timer;
String get _timerText {
final secondsPerMinute = 60;
final secondsLeft = _maxSeconds - _currentSecond;
final formattedMinutesLeft =
(secondsLeft ~/ secondsPerMinute).toString().padLeft(2, '0');
final formattedSecondsLeft =
(secondsLeft % secondsPerMinute).toString().padLeft(2, '0');
print('$formattedMinutesLeft : $formattedSecondsLeft');
return '$formattedMinutesLeft : $formattedSecondsLeft';
}
@override
void initState() {
super.initState();
_startTimer();
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.timer),
Text(_timerText),
],
),
),
);
}
void _startTimer() {
final duration = Duration(seconds: 1);
_timer = Timer.periodic(duration, (Timer timer) {
setState(() {
_currentSecond = timer.tick;
if (timer.tick >= _maxSeconds) timer.cancel();
});
});
}
}
I've Created a amazing timer without any plugin, here you can also get count down timer.我创建了一个没有任何插件的惊人计时器,在这里你也可以得到倒数计时器。 And don't forget to stop the timer on back pressed.并且不要忘记在按下后停止计时器。
Here is the link of my timer full Project.这是我的计时器完整项目的链接。 * Hope this will help someone. *希望这会对某人有所帮助。 Thank you.谢谢你。 * *
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: AttendanceScreen(),
);
}
}
class AttendanceScreen extends StatefulWidget {
AttendanceScreen();
@override
_AttendanceScreenState createState() => _AttendanceScreenState();
}
class _AttendanceScreenState extends State<AttendanceScreen> {
static var countdownDuration = Duration(minutes: 10);
static var countdownDuration1 = Duration(minutes: 10);
Duration duration = Duration();
Duration duration1 = Duration();
Timer? timer;
Timer? timer1;
bool countDown = true;
bool countDown1 = true;
@override
void initState() {
var hours;
var mints;
var secs;
hours = int.parse("00");
mints = int.parse("00");
secs = int.parse("00");
countdownDuration = Duration(hours: hours, minutes: mints, seconds: secs);
startTimer();
reset();
var hours1;
var mints1;
var secs1;
hours1 = int.parse("10");
mints1 = int.parse("00");
secs1 = int.parse("00");
countdownDuration1 =
Duration(hours: hours1, minutes: mints1, seconds: secs1);
startTimer1();
reset1();
super.initState();
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text("Timer Example"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
color: Colors.white,
onPressed: () {
_onWillPop();
},
),
),
body: Container(
color: Colors.black12,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 20,
),
Text(
"Timer",
style: TextStyle(fontSize: 25),
),
Container(
margin: EdgeInsets.only(top: 30, bottom: 30),
child: buildTime()),
SizedBox(
height: 20,
),
Text(
"Count down timer",
style: TextStyle(fontSize: 25),
),
Container(
margin: EdgeInsets.only(top: 30, bottom: 30),
child: buildTime1()),
]),
),
),
);
}
Future<bool> _onWillPop() async {
final isRunning = timer == null ? false : timer!.isActive;
if (isRunning) {
timer!.cancel();
}
Navigator.of(context, rootNavigator: true).pop(context);
return true;
}
void reset() {
if (countDown) {
setState(() => duration = countdownDuration);
} else {
setState(() => duration = Duration());
}
}
void reset1() {
if (countDown) {
setState(() => duration1 = countdownDuration1);
} else {
setState(() => duration1 = Duration());
}
}
void startTimer() {
timer = Timer.periodic(Duration(seconds: 1), (_) => addTime());
}
void startTimer1() {
timer = Timer.periodic(Duration(seconds: 1), (_) => addTime1());
}
void addTime() {
final addSeconds = 1;
setState(() {
final seconds = duration.inSeconds + addSeconds;
if (seconds < 0) {
timer?.cancel();
} else {
duration = Duration(seconds: seconds);
}
});
}
void addTime1() {
final addSeconds = 1;
setState(() {
final seconds = duration1.inSeconds - addSeconds;
if (seconds < 0) {
timer1?.cancel();
} else {
duration1 = Duration(seconds: seconds);
}
});
}
Widget buildTime() {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final hours = twoDigits(duration.inHours);
final minutes = twoDigits(duration.inMinutes.remainder(60));
final seconds = twoDigits(duration.inSeconds.remainder(60));
return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
buildTimeCard(time: hours, header: 'HOURS'),
SizedBox(
width: 8,
),
buildTimeCard(time: minutes, header: 'MINUTES'),
SizedBox(
width: 8,
),
buildTimeCard(time: seconds, header: 'SECONDS'),
]);
}
Widget buildTime1() {
String twoDigits(int n) => n.toString().padLeft(2, '0');
final hours = twoDigits(duration1.inHours);
final minutes = twoDigits(duration1.inMinutes.remainder(60));
final seconds = twoDigits(duration1.inSeconds.remainder(60));
return Row(mainAxisAlignment: MainAxisAlignment.center, children: [
buildTimeCard(time: hours, header: 'HOURS'),
SizedBox(
width: 8,
),
buildTimeCard(time: minutes, header: 'MINUTES'),
SizedBox(
width: 8,
),
buildTimeCard(time: seconds, header: 'SECONDS'),
]);
}
Widget buildTimeCard({required String time, required String header}) =>
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.white, borderRadius: BorderRadius.circular(20)),
child: Text(
time,
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
fontSize: 50),
),
),
SizedBox(
height: 24,
),
Text(header, style: TextStyle(color: Colors.black45)),
],
);
}
Many answer already provided.已经提供了许多答案。 I suggest a shortcut way-我建议一种快捷方式-
Use this package Custom_timer使用这个包Custom_timer
Add this to your package's pubspec.yaml file:将此添加到包的 pubspec.yaml 文件中:
dependencies:
custom_timer: ^0.0.3
(use latest version) (使用最新版本)
and very simple to implement并且实现起来非常简单
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: Text("CustomTimer example"),
),
body: Center(
child: CustomTimer(
from: Duration(hours: 12),
to: Duration(hours: 0),
onBuildAction: CustomTimerAction.auto_start,
builder: (CustomTimerRemainingTime remaining) {
return Text(
"${remaining.hours}:${remaining.minutes}:${remaining.seconds}",
style: TextStyle(fontSize: 30.0),
);
},
),
),
),
);
}
You can use this plugin timer_builder你可以使用这个插件timer_builder
timer_builder widget that rebuilds itself on scheduled, periodic, or dynamically generated time events. timer_builder 小部件,它在计划的、定期的或动态生成的时间事件上重建自己。
Examples例子
Periodic rebuild定期重建
import 'package:timer_builder/timer_builder.dart';
class ClockWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TimerBuilder.periodic(Duration(seconds: 1),
builder: (context) {
return Text("${DateTime.now()}");
}
);
}
}
Rebuild on a schedule按计划重建
import 'package:timer_builder/timer_builder.dart';
class StatusIndicator extends StatelessWidget {
final DateTime startTime;
final DateTime endTime;
StatusIndicator(this.startTime, this.endTime);
@override
Widget build(BuildContext context) {
return TimerBuilder.scheduled([startTime, endTime],
builder: (context) {
final now = DateTime.now();
final started = now.compareTo(startTime) >= 0;
final ended = now.compareTo(endTime) >= 0;
return Text(started ? ended ? "Ended": "Started": "Not Started");
}
);
}
}
For showing your total seconds in this format hh:mm:ss, you can use below method:要以这种格式 hh:mm:ss 显示您的总秒数,您可以使用以下方法:
String getDuration(int totalSeconds) {
String seconds = (totalSeconds % 60).toInt().toString().padLeft(2, '0');
String minutes =
((totalSeconds / 60) % 60).toInt().toString().padLeft(2, '0');
String hours = (totalSeconds ~/ 3600).toString().padLeft(2, '0');
return "$hours\:$minutes\:$seconds";
}
import 'package:rxdart/rxdart.dart';
final BehaviorSubject<int> resendTimeController = BehaviorSubject<int>();
static const timerDuration = 90;
int resendTimer = 0;
Timer? timer;
void startTimer() {
timer?.cancel();
resendTimer = timerDuration;
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (resendTimer > 0) {
resendTimer--;
resendTimeController.add(resendTimer);
if (resendTimer == 0) {
timer.cancel();
}
}
});
}
and use intl this
StreamBuilder<int>(
stream: _bloc.resendTimeController,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Container();
}
final DateTime date = DateTime.fromMillisecondsSinceEpoch(snapshot.data! * 1000);
return GestureDetector(
onTap: () {
if (snapshot.data == 0) {
_bloc.resendCode();
}
},
child: Text(
snapshot.data! > 0 ? 'Resend code ${DateFormat('mm:ss').format(date)}' : 'Resend SMS',
),
);
},
),
import 'package:async/async.dart';
late CancelableOperation? cancellableOperation;
int counter = 5;
StatefulBuilder(
builder: (context, setState) {
if (counter > 0) {
cancellableOperation = CancelableOperation.fromFuture(
Future.delayed(const Duration(seconds: 1)),
onCancel: () => {},
);
cancellableOperation?.value.whenComplete(() => setState(() => counter--));
return buildButton(
text: 'Wait($counter)',
textColor: getTextColor,
backgroundColor: Colors.grey.withOpacity(0.5),
onPressed: () {},
);
}
return buildButton(
text: 'Complete',
textColor: Colors.green,
backgroundColor: Colors.greenAccent.withOpacity(0.5),
onPressed: () {},
);
},
)
I did something like this for my dialog's complete button.我为对话框的完成按钮做了类似的事情。 It counts for 5 seconds before to show complete button.它会在显示完成按钮之前计数 5 秒。 But do not forget to call cancellableOperation?.cancel()
if you close the dialog or page before counting complete.但是,如果在计数完成之前关闭对话框或页面,请不要忘记调用cancellableOperation?.cancel()
。
Countdown timer in one line倒数计时器在一行
CountdownTimer(Duration(seconds: 5), Duration(seconds: 1)).listen((data){
})..onData((data){
print('data $data');
})..onDone((){
print('onDone.........');
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.