Flutter:显示分钟和秒的倒数计时器

Posted

技术标签:

【中文标题】Flutter:显示分钟和秒的倒数计时器【英文标题】:Flutter: Countdown timer that displays minutes and seconds 【发布时间】:2020-04-19 15:58:05 【问题描述】:

我创建了一个倒数计时器,它将从用户输入的持续时间开始倒计时,以分钟为单位。

倒数计时器在技术上有效,但仅显示分钟数。秒数始终保持在 :00。

如何让秒数也显示为倒计时的一部分?

这里是相关代码,摘自一个较长的文件。如果需要,我可以添加更多内容。

各段代码分解如下:

首先,我有一个实际显示计时器文本并允许对其进行样式设置的类:

class Countdown extends AnimatedWidget 
  Countdown( Key key, this.animation ) : super(key: key, listenable: animation);
  Animation<int> animation;

  @override

  build(BuildContext context)

    Duration clockTimer = Duration(seconds: animation.value*60);

    String timerText = '$clockTimer.inMinutes.remainder(60).toString():$(clockTimer.inSeconds.remainder(60) % 60).toString().padLeft(2, '0')';

    return Text(
      "$timerText",
      style: TextStyle(         
        fontSize: 110,
        color: Theme.of(context).primaryColor,
      ),
    );

  

我有一个动画控制器如下:

AnimationController _controller;

  @override

  void dispose()
    _controller.dispose();
    super.dispose();
  

  void initState() 
    super.initState();
    @override

      _controller = AnimationController(
          vsync: this,
        duration: Duration(minutes: gameData.levelClock)  // gameData.levelClock is a user entered number elsewhere in the applciation
      );


  

最后是调用 Countdown 小部件的代码部分:

Countdown(
     animation: StepTween(
     begin: gameData.levelClock,   // THIS IS A USER ENTERED NUMBER 
     end: 0,
   ).animate(_controller),
)

感谢您提供的任何帮助。

【问题讨论】:

【参考方案1】:

您可以在下面复制粘贴运行完整代码 您的 AnimationController 持续时间需要使用秒 代码sn-p

_controller = AnimationController(
        vsync: this,
        duration: Duration(
            seconds:
                levelClock) // gameData.levelClock is a user entered number elsewhere in the applciation
        );

工作演示

完整代码

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin 
  int _counter = 0;
  AnimationController _controller;
  int levelClock = 180;

  void _incrementCounter() 
    setState(() 
      _counter++;
    );
  

  @override
  void dispose() 
    _controller.dispose();
    super.dispose();
  

  @override
  void initState() 
    super.initState();

    _controller = AnimationController(
        vsync: this,
        duration: Duration(
            seconds:
                levelClock) // gameData.levelClock is a user entered number elsewhere in the applciation
        );

    _controller.forward();
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Countdown(
              animation: StepTween(
                begin: levelClock, // THIS IS A USER ENTERED NUMBER
                end: 0,
              ).animate(_controller),
            ),
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  


class Countdown extends AnimatedWidget 
  Countdown(Key key, this.animation) : super(key: key, listenable: animation);
  Animation<int> animation;

  @override
  build(BuildContext context) 
    Duration clockTimer = Duration(seconds: animation.value);

    String timerText =
        '$clockTimer.inMinutes.remainder(60).toString():$clockTimer.inSeconds.remainder(60).toString().padLeft(2, '0')';

    print('animation.value  $animation.value ');
    print('inMinutes $clockTimer.inMinutes.toString()');
    print('inSeconds $clockTimer.inSeconds.toString()');
    print('inSeconds.remainder $clockTimer.inSeconds.remainder(60).toString()');

    return Text(
      "$timerText",
      style: TextStyle(
        fontSize: 110,
        color: Theme.of(context).primaryColor,
      ),
    );
  

【讨论】:

如何使用文本大小 "vsync: this" 显示错误,无法编译。 @Kamlesh,我再次完整测试。它工作正常。你忘了使用 TickerProviderStateMixin => State 和 TickerProviderStateMixin【参考方案2】:

所以问题在于,当您创建 CountDown 小部件时,您将 begin 设置为一个 double 值,这是您的计时器的分钟值(对于此示例,该值是 5)。随着动画的继续,它将从begin 倒计时到end(在这种情况下为0)。超过 5 分钟,它会从 5 变为 0。

然后您使用该值并将其转换为秒,但由于动画的值介于 0 和 5 之间,它总是会给您 5:00、4:00、3:00、2:00、1:00 或0:00。

解决方案是将您的代码更改为

Countdown(
     animation: StepTween(
     begin: gameData.levelClock * 60, // convert to seconds here
     end: 0,
   ).animate(_controller),
)

然后在倒计时小部件中将Duration 更改为

Duration clockTimer = Duration(seconds: animation.value);

您可以在 DartPad here 上找到一个工作示例

【讨论】:

如果想通过单击按钮重新开始倒计时,有什么办法吗? @ali 是的,只需调用_controller.reset() 将动画控制器重置为其初始值,然后调用_controller.forward() 再次启动动画

以上是关于Flutter:显示分钟和秒的倒数计时器的主要内容,如果未能解决你的问题,请参考以下文章

如何通过单击按钮启动倒数计时器事件?

Flutter 中的倒数计时器日期和时间格式

具有可配置开始时间的 JQuery 倒数计时器

Flutter:当倒数计时器达到 0 时执行动作

在按钮上显示倒数计时器

颤振倒数计时器