Flutter 倒计时计时器

135

我该怎么做才能将传递给构造函数的值用于创建一个四舍五入到小数点后一位的定时器,并显示在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),
        ),
      ),
    );
  }
}

请添加一些代码,您的问题不够清晰。 - satish
1
是的,只需使用 setState 来更新值,不要在其中放置任何小部件。 - Yann39
计时器的代码是什么?你能给我提供一个链接吗? - Floris Marpepa
使用 Timer 类来表示一个可以使用 Timer.periodic 重复触发的计时器。您还可以查看 Stopwatch 类。 - Yann39
14个回答

293

以下是使用 Timer.periodic 的示例:

点击按钮后,倒计时从 100 开始:

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")
      ],
    ),
  );
}

结果:

Flutter倒计时计时器示例

你也可以使用来自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")
      ],
    ),
  );
}

编辑: 针对评论中有关按钮单击行为的问题

使用上述代码,每次点击按钮将启动一个新计时器,所有这些计时器都将更新相同的_start变量,导致计数器快速递减。

有多种解决方案可更改此行为,具体取决于您想要实现什么目标:

  • 禁用按钮一旦被点击,以便用户无法再干扰倒计时(也许在计时器被取消后重新启用它)
  • 使用非空条件包装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(...);
}

您也可以使用官方的async包,该包提供了一个RestartableTimer类,它继承自Timer并添加了reset方法。

因此,只需在每次按钮点击时调用_timer.reset();即可。

最后,Codepen现在支持Flutter!这里有一个实时示例,让大家一起玩耍:https://codepen.io/Yann39/pen/oNjrVOb


看到你的代码有助于我理解一些。现在我有一些问题。Timer和Timer.periodic之间有什么区别?如果我想制作一个像你的倒计时计时器,但是还要显示第一个小数,应该怎么做? - Floris Marpepa
5
Timer 创建一个新的定时器,其回调函数在指定的持续时间后仅被调用一次(例如,延迟操作)。Timer.periodic 创建一个新的重复计时器,使得回调函数根据指定的持续时间间隔重复调用。如果要显示小数,请使用double而不是int。如果您的问题是要将时间间隔减少0.1,则只需在上面的代码中将1更改为0.1即可。最后,如果您需要格式化输出,请参阅NumberFormat - Yann39
1
你可以将计时器的开始时间存储在共享首选项中,然后在应用程序启动时,将计时器值设置为当前时间减去开始时间的秒数。 - Yann39
1
@AndrewCaprario 我在答案的结尾添加了更多信息,因为这太长了无法作为评论。我还添加了一个CodePen链接。 - Yann39
1
@Coltuxumab 只需将计数器放在另一个小部件中,并具有自己的构建方法即可。 - Yann39
显示剩余11条评论

50
我创建了一个通用的计时器小部件,可以用于显示任何类型的计时器,并且非常灵活。
此小部件具有以下属性:
1. secondsRemaining:以秒为单位计算计时器需要运行的持续时间。 2. whenTimeExpires:计时器完成后需要执行的操作。 3. countDownStyle:任何您想要为计时器设置的样式。 4. countDownFormatter:用户想要显示倒计时计时器的方式,例如“hh mm ss”字符串,如“01小时:20分钟:45秒”。
如果您不想从每个位置提供它,则可以提供默认格式化程序(formatHHMMSS)。
// 为此提供实现 - formatHHMMSS(duration.inSeconds) 或使用我提供的下面的实现。
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,
              );
            }));
  }
}

使用方法:

 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,
            ),
          ),
        )

formatHHMMSS的示例:

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";
}

上述代码的空值安全版本

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,
          );
        },
      ),
    );
  }
}


1
我有些困难,我们能否添加运行时开始和停止计时器? - IamVariable
倒计时格式化器的实现是什么? - dazza5000
不错的东西,伙计!如何实现暂停。 - The Billionaire Guy
请问如何实现暂停功能。先感谢您的回答。 - The Billionaire Guy
谢谢!我该如何让它计数而不是倒数?是否有一种方法可以放置一个监听器,以便在用户按下按钮并从屏幕导航时可以打印经过的计时时间? - VegetaSaiyan
显示剩余3条评论

39

可能有点晚,但为什么你们不试试动画呢?我并不是让你管理动画控制器、处理它们之类的东西,Flutter有一个名为TweenAnimationBuilder的内置小部件来帮助你。你可以在任何类型的值之间进行动画交替,以下是一个使用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)));
    }),

你还可以获得onEnd回调,它在动画完成时通知你;

以下是输出结果:


这里展示的示例代码https://api.flutter.dev/flutter/widgets/TweenAnimationBuilder-class.html非常适合进行简单平滑的动画制作。我用它来制作了一个线性进度指示器条。 - Eradicatore
1
如果您的项目支持空安全,请将构建器更改为 Widget? child - Volker Andres
你如何在时间结束后重新启动它? - SULPHURIC ACID
@SULPHURICACID 很抱歉,我们无法重新启动,因为我们没有任何动画控制器。也许您应该考虑定义一个动画控制器并使用它。 - Mahesh Jamdade
如何显示当前时间的计时器。 - MohammedAli
显示剩余2条评论

23
这是我的计时器小部件,与问题无关,但可能会对某些人有所帮助。

这是我的计时器小部件,与问题无关,但可能会对某些人有所帮助。

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)
      ],
    );
  }
}

你会得到类似这样的东西

输入图像描述


6
你需要将 startTimeout 函数包裹在挂载检查小部件的代码中,像这样 if(mounted){startTimeout();},否则你会因为 setState 和异步代码的影响而导致内存泄漏。 - Ali Abbas

18

虽然不直接回答你的问题,但对于那些想在一段时间后开始某事的人很有帮助。

Future.delayed(Duration(seconds: 1), () {
            print('yo hey');
          });

2
在Flutter /移动应用程序中,延迟操作能否在其宿主程序被终止时存活? - Yu Shen
没有相关的问题,但这正是我所寻找的。谢谢 - Rohit Rawat
每当用户按下按钮时如何终止旧计时器并创建一个新的计时器? - user14023416

11
我已经创建了一个令人惊叹的计时器,没有使用任何插件,你可以在这里获得倒计时器。不要忘记在按下返回按钮时停止计时器。
以下是我的完整计时器项目链接:
* 希望这能帮到一些人。谢谢。 请点击以下链接查看图片:enter image description here
   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)),
        ],
      );
}

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。-【来自审查】 - Sercan Sebetçi

7

如果你只需要一个简单的倒计时器,那么这是一个不错的选择,而不必安装一个软件包。祝编码愉快!

countDownTimer() async {
 int timerCount;
 for (int x = 5; x > 0; x--) {
   await Future.delayed(Duration(seconds: 1)).then((_) {
     setState(() {
       timerCount -= 1;
    });
  });
 }
}

4
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();
      });
    });
  }
}

3

要以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";


}

这非常有帮助,在我的情况下,我只需要一个基于文本的计时器,根据剩余时间自定义颜色。所以这对我来说非常完美。感谢它的简单易用。谢谢! - RobbB

3

我正在使用flutter_countdown_timer

依赖项: flutter_countdown_timer: ^1.0.0

$ flutter pub get

CountdownTimer(endTime: 1594829147719)

1594829147719是您的时间戳(以毫秒为单位)


嗨,Ricardo,我也在使用这个..我有一个问题,也许你可以帮忙。你能告诉我如何更改计时器结束时出现的默认文本吗?我尝试使用OnEnd()函数返回文本,但似乎不起作用... - Ashootosh Bhardwaj
我的问题是如何创建和销毁控制器?我不理解这个包的文档。他们初始化控制器,然后再次重新分配所有东西? - Michael Tolsma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接