我正在使用 RestartableTimer
(Timer
的子类)作为倒数计时器,在一定时间后将人们“踢出”表格。
我想显示那个计时器的进度,我喜欢循环进度慢慢填满的想法。
我没有展示我的代码,因为我真的没有什么可展示的。我在一个小部件中有一个完全静态的进度指示器和一个工作计时器(有状态或无状态,以效果最好的为准)。
我面临两个问题,这是我需要帮助的地方:
我不知道如何每 x 毫秒检查一次计时器进度。我怎样才能做到这一点?我不需要复制粘贴代码,但我应该去了解更多“什么对象/哪个方向”?
计时器进度未实现(NotImplementedException);有什么办法可以在其他地方找到等价物吗?除了那个部分,那个对象对我来说真的很好用。
我是 SOL 还是有办法做到这一点?
最佳答案
在 getter tick
中没有什么要实现的,因为 RestartableTimer
不是周期性的。您想要的是一个复杂得多的东西,RestartableTimer
无法帮助您。
首先,您需要一些东西来控制 CircularProgressIndicator
的进度:
class ProgressController {
static const double smoothnessConstant = 250;
final Duration duration;
final Duration tickPeriod;
Timer _timer;
Timer _periodicTimer;
Stream<void> get progressStream => _progressController.stream;
StreamController<void> _progressController = StreamController<void>.broadcast();
Stream<void> get timeoutStream => _timeoutController.stream;
StreamController<void> _timeoutController = StreamController<void>.broadcast();
double get progress => _progress;
double _progress = 0;
ProgressController({@required this.duration})
: assert(duration != null),
tickPeriod = _calculateTickPeriod(duration);
void start() {
_timer = Timer(duration, () {
_cancelTimers();
_setProgressAndNotify(1);
_timeoutController.add(null);
});
_periodicTimer = Timer.periodic(
tickPeriod,
(Timer timer) {
double progress = _calculateProgress(timer);
_setProgressAndNotify(progress);
},
);
}
void restart() {
_cancelTimers();
start();
}
Future<void> dispose() async {
await _cancelStreams();
_cancelTimers();
}
double _calculateProgress(Timer timer) {
double progress = timer.tick / smoothnessConstant;
if (progress > 1) return 1;
if (progress < 0) return 0;
return progress;
}
void _setProgressAndNotify(double value) {
_progress = value;
_progressController.add(null);
}
Future<void> _cancelStreams() async {
if (!_progressController.isClosed) await _progressController.close();
if (!_timeoutController.isClosed) await _timeoutController.close();
}
void _cancelTimers() {
if (_timer?.isActive == true) _timer.cancel();
if (_periodicTimer?.isActive == true) _periodicTimer.cancel();
}
static Duration _calculateTickPeriod(Duration duration) {
double tickPeriodMs = duration.inMilliseconds / smoothnessConstant;
return Duration(milliseconds: tickPeriodMs.toInt());
}
}
然后你可以实现一个 CircularProgressIndicator
来监听来自 ProgressController
的 Stream
:
class RestartableCircularProgressIndicator extends StatefulWidget {
final ProgressController controller;
final VoidCallback onTimeout;
RestartableCircularProgressIndicator({
Key key,
@required this.controller,
this.onTimeout,
}) : assert(controller != null),
super(key: key);
@override
_RestartableCircularProgressIndicatorState createState() =>
_RestartableCircularProgressIndicatorState();
}
class _RestartableCircularProgressIndicatorState
extends State<RestartableCircularProgressIndicator> {
ProgressController get controller => widget.controller;
VoidCallback get onTimeout => widget.onTimeout;
@override
void initState() {
super.initState();
controller.progressStream.listen((_) => updateState());
controller.timeoutStream.listen((_) => onTimeout());
}
@override
Widget build(BuildContext context) {
return CircularProgressIndicator(
value: controller.progress,
);
}
void updateState() => setState(() {});
}
您还可以将 CircularProgressIndicator
的一些参数传递给 RestartableCircularProgressIndicator
,这样您就可以对其进行自定义。
一个用法示例:
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ProgressController controller;
@override
void initState() {
super.initState();
controller = ProgressController(
duration: Duration(seconds: 5),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
RestartableCircularProgressIndicator(
controller: controller,
onTimeout: () => print('timeout'),
),
RaisedButton(
onPressed: controller.start,
child: Text('Start'),
),
RaisedButton(
onPressed: controller.restart,
child: Text('Restart'),
),
],
),
),
),
);
}
}
有一天我会把它转换成一个库,但在那之前我无法提供这段代码的测试和文档,所以如果你想了解这里发生了什么,你必须研究它(对不起...... ).
关于flutter - 在 flutter 中的 CircularProgressIndicator 上显示计时器进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56853554/