如何将传递的值放入构造中,使计时器 四舍五入到小数点后一位并显示在RaisedButton的子文本中? 我尝试过但没有运气。我设法使用 一个简单的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 :
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) => setState( () { if (_start < 1) { timer.cancel(); } else { _start = _start - 1; } }, ), ); } @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 :
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 :
wrap the Timer.periodic creation with a non null condition so that clicking the button multiple times has no effect
if (_timer != null) { _timer = new Timer.periodic(…); }
cancel the timer and reset the countdown if you want to restart the timer on each click :
if (_timer != null) { _timer.cancel(); _start = 10; } _timer = new Timer.periodic(…);
if you want the button to act like a play/pause button :
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
reset
So just call _timer.reset(); on each button click.
_timer.reset();
Finally, Codepen now supports Flutter ! So here is a live example so that everyone can play with it : https://codepen.io/Yann39/pen/oNjrVOb