Timer 如何在颤振中从零开始计时?

Timer 如何在颤振中从零开始计时?,timer,flutter,Timer,Flutter,我试图显示一个计时器(dd HH mm ss格式)来计算每个动作之间的时间(例如按钮动作)。即使应用程序关闭并重建,也需要工作。当前,我加载了一个字符串日期,该日期是我按下按钮时用SharedReference保存的,表示我按下按钮时的时间。我格式化所有时间小数以比较和显示时间差。我觉得它不漂亮,不是我搜索的,我也没有成功地以这种格式显示时钟(dd-HH-mm-ss)。如果有人有一个更简单的例子:) 我也试过这段代码,没关系,当我调用函数时计时器会增加,但我不想要datenow,我只需要从零时间

我试图显示一个计时器(dd HH mm ss格式)来计算每个动作之间的时间(例如按钮动作)。即使应用程序关闭并重建,也需要工作。当前,我加载了一个字符串日期,该日期是我按下按钮时用SharedReference保存的,表示我按下按钮时的时间。我格式化所有时间小数以比较和显示时间差。我觉得它不漂亮,不是我搜索的,我也没有成功地以这种格式显示时钟(dd-HH-mm-ss)。如果有人有一个更简单的例子:)

我也试过这段代码,没关系,当我调用函数时计时器会增加,但我不想要datenow,我只需要从零时间开始

int _start = 0;
  void startTimer() {
    _start=0;
    var now = new DateTime.now();
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
        oneSec,
            (Timer timer) => setState(() {
        {
          chrono = now.add(new Duration(seconds: _start));
            _start = _start + 1;
          }
        }));
  }
编辑:我找到了这个解决方案,但有一些生命周期错误,如果我关闭应用程序,我会松开计时器

 Stopwatch stopwatch = new Stopwatch();


  void rightButtonPressed() {
    setState(() {
      if (stopwatch.isRunning) {
        stopwatch.reset();
      } else {
        stopwatch.reset();
        stopwatch.start();
      }
    });
  }
 @override
  Widget build(BuildContext context)
  {
...
     new Container(height: 80.0,
            child: new Center(
              child: new TimerText(stopwatch: stopwatch),
            )),

...
class TimerText extends StatefulWidget {
  TimerText({this.stopwatch});
  final Stopwatch stopwatch;

  TimerTextState createState() => new TimerTextState(stopwatch: stopwatch);
}

class TimerTextState extends State<TimerText> {

  Timer timer;
  final Stopwatch stopwatch;

  TimerTextState({this.stopwatch}) {
    timer = new Timer.periodic(new Duration(milliseconds: 30), callback);
  }

  void callback(Timer timer) {
    if (stopwatch.isRunning) {
      setState(() {

      });
    }
  }

  @override
  Widget build(BuildContext context) {
    final TextStyle timerTextStyle = const TextStyle(fontSize: 50.0, fontFamily: "Open Sans");
    String formattedTime = TimerTextFormatter.format(stopwatch.elapsedMilliseconds);
    return new Text(formattedTime, style: timerTextStyle);
  }
}

class TimerTextFormatter {
  static String format(int milliseconds) {

    int seconds = (milliseconds / 1000).truncate();
    int minutes = (seconds / 60).truncate();
    int hours = (minutes / 60).truncate();
    int days = (hours / 24).truncate();
    String minutesStr = (minutes % 60).toString().padLeft(2, '0');
    String secondsStr = (seconds % 60).toString().padLeft(2, '0');
    String hoursStr = (hours % 60).toString().padLeft(2, '0');
    String daysStr = (days % 24).toString().padLeft(2, '0');
    return "$daysStr:$hoursStr:$minutesStr:$secondsStr";
  }
}
秒表秒表=新秒表();
void rightButtonPressed(){
设置状态(){
if(秒表正在运行){
秒表复位();
}否则{
秒表复位();
秒表。开始();
}
});
}
@凌驾
小部件构建(构建上下文)
{
...
新容器(高度:80.0,
孩子:新中心(
子项:新TimerText(秒表:秒表),
)),
...
类TimerText扩展StatefulWidget{
TimerText({this.stopwatch});
最后的秒表;
TimerTextState createState()=>新的TimerTextState(秒表:秒表);
}
类TimerTextState扩展状态{
定时器;
最后的秒表;
TimerTextState({this.stopwatch}){
计时器=新的计时器。周期(新的持续时间(毫秒:30),回调);
}
无效回调(计时器){
if(秒表正在运行){
设置状态(){
});
}
}
@凌驾
小部件构建(构建上下文){
final TextStyle timerTextStyle=常量TextStyle(fontSize:50.0,fontFamily:“开放式SAN”);
String formattedTime=TimerTextFormatter.format(秒表.elapsedmillyses);
返回新文本(formattedTime,样式:timerTextStyle);
}
}
类TimerTextFormatter{
静态字符串格式(整数毫秒){
int seconds=(毫秒/1000).truncate();
int minutes=(秒/60).truncate();
整小时=(分钟/60).truncate();
整数天=(小时/24).truncate();
字符串minutesStr=(分钟数%60).toString().padLeft(2,'0');
字符串secondsStr=(秒数%60).toString().padLeft(2,'0');
字符串hoursStr=(小时数%60).toString().padLeft(2,'0');
字符串daysStr=(天%24).toString().padLeft(2,'0');
返回“$daysStr:$hourstr:$minutesStr:$secondsStr”;
}
}

如果您希望计数器在关闭应用程序后保持不变,则无法将值保存在某个位置(如共享首选项)

使用dateTime.toIso8601String()和dateTime.parse()可以减少保存和加载的麻烦。 要计算通过的时间,可以使用DateTime.now().difference(lastButtonPressed)

应该有一个函数来格式化Duration(),但它尚未实现。我在这里找到了一个:

下面是一个小例子:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutterfly/SharedPrefs.dart';

class TestWidget extends StatefulWidget {
  @override
  _TestWidgetState createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget> {
  DateTime _lastButtonPress;
  String _pressDuration;
  Timer _ticker;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text("Time since button pressed"),
          Text(_pressDuration),
          RaisedButton(
            child: Text("Press me"),
            onPressed: () {
              _lastButtonPress = DateTime.now();
              _updateTimer();
              sharedPreferences.setString("lastButtonPress",_lastButtonPress.toIso8601String());
            },
          )
        ],
      ),
    );
  }


  @override
  void initState() {
    super.initState();
    final lastPressString = sharedPreferences.getString("lastButtonPress");
    _lastButtonPress = lastPressString!=null ? DateTime.parse(lastPressString) : DateTime.now();
    _updateTimer();
    _ticker = Timer.periodic(Duration(seconds:1),(_)=>_updateTimer());
  }


  @override
  void dispose() {
    _ticker.cancel();
    super.dispose();
  }



  void _updateTimer() {
    final duration = DateTime.now().difference(_lastButtonPress);
    final newDuration = _formatDuration(duration);
    setState(() {
      _pressDuration = newDuration;
    });
  }

  String _formatDuration(Duration duration) {
    String twoDigits(int n) {
      if (n >= 10) return "$n";
      return "0$n";
    }

    String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
    String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
    return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
  }
}
导入'dart:async';
进口“包装:颤振/材料.省道”;
导入“包:flutfly/SharedPrefs.dart”;
类TestWidget扩展了StatefulWidget{
@凌驾
_TestWidgetState createState();
}
类_TestWidgetState扩展了状态{
DateTime\u lastButton按;
字符串持续时间;
定时器;
@凌驾
小部件构建(构建上下文){
返回中心(
子:列(
mainAxisAlignment:mainAxisAlignment.center,
儿童:[
文本(“按钮按下后的时间”),
文字(_pressDuration),
升起的按钮(
孩子:文本(“按我”),
已按下:(){
_lastButtonPress=DateTime.now();
_updateTimer();
sharedPreferences.setString(“lastButtonPress”,u lastButtonPress.toIso8601String());
},
)
],
),
);
}
@凌驾
void initState(){
super.initState();
final lastPressString=SharedReferences.getString(“lastButtonPress”);
_lastButtonPress=lastPressString!=null?DateTime.parse(lastPressString):DateTime.now();
_updateTimer();
_ticker=Timer.periodic(持续时间(秒:1),()=>updateTimer());
}
@凌驾
无效处置(){
_ticker.cancel();
super.dispose();
}
void _updateTimer(){
最终持续时间=DateTime.now().difference(_lastbutonpress);
最终newDuration=_formatDuration(duration);
设置状态(){
_按持续时间=新建持续时间;
});
}
字符串\u formatDuration(持续时间){
字符串两位数(整数n){
如果(n>=10)返回“$n”;
返回“0$n”;
}
字符串twoDigitMinutes=twoDigits(持续时间.inMinutes.余数(60));
字符串twoDigitSeconds=twoDigits(duration.unseconds.rements(60));
返回“${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds”;
}
}
为了简单起见,我在全局范围内的main方法中初始化了共享首选项。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutterfly/SharedPrefs.dart';

class TestWidget extends StatefulWidget {
  @override
  _TestWidgetState createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget> {
  DateTime _lastButtonPress;
  String _pressDuration;
  Timer _ticker;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text("Time since button pressed"),
          Text(_pressDuration),
          RaisedButton(
            child: Text("Press me"),
            onPressed: () {
              _lastButtonPress = DateTime.now();
              _updateTimer();
              sharedPreferences.setString("lastButtonPress",_lastButtonPress.toIso8601String());
            },
          )
        ],
      ),
    );
  }


  @override
  void initState() {
    super.initState();
    final lastPressString = sharedPreferences.getString("lastButtonPress");
    _lastButtonPress = lastPressString!=null ? DateTime.parse(lastPressString) : DateTime.now();
    _updateTimer();
    _ticker = Timer.periodic(Duration(seconds:1),(_)=>_updateTimer());
  }


  @override
  void dispose() {
    _ticker.cancel();
    super.dispose();
  }



  void _updateTimer() {
    final duration = DateTime.now().difference(_lastButtonPress);
    final newDuration = _formatDuration(duration);
    setState(() {
      _pressDuration = newDuration;
    });
  }

  String _formatDuration(Duration duration) {
    String twoDigits(int n) {
      if (n >= 10) return "$n";
      return "0$n";
    }

    String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
    String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
    return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
  }
}