如何在颤动中从零开始启动计数器?

时间:2019-05-25 14:51:35

标签: timer flutter

我试图显示一个计时器(格式为dd HH mm ss)以计算每个动作(例如按钮动作)之间的时间。并且需要工作,即使应用程序已关闭并重建。当前,当我按下一个按钮时,我加载了使用sharedpreference保存的字符串日期,该日期代表按下按钮的时间。我格式化所有时间小数点以进行比较并显示时差。我认为它不是很漂亮,不是我要搜索的内容,并且我没有成功以(dd HH mm ss)格式显示时钟。如果有人有一个更简单的例子:)

load_records_pulsion() async{

    /*var current_time = DateFormat('yyyy-MM-dd HH').format(DateTime.now());*/
    SharedPreferences prefs = await SharedPreferences.getInstance();
    setState(() {
      RegExp regExp = new RegExp(            //Here is the regex time pulsion
        r"([12]\d{3})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])",
      );
      last_pulsion = (prefs.getString('last_pulsion'))??0;


      var match = regExp.firstMatch("$last_pulsion");
      annees = match.group(1);   // hh:mm
      mois = match.group(2);   // hh:mm
      jours = match.group(3);   // hh:mm

      int annees_int = int.tryParse("$annees") ;
      int mois_int = int.tryParse("$mois") ;
      int jours_int = int.tryParse("$jours") ;
      print("$annees_int");
      print("$mois_int");
      print("$jours_int");


      final last_pulsion2 = DateTime(annees_int, mois_int, jours_int);
      final date_now = DateTime.now();
      difference_pulsion = date_now.difference(last_pulsion2).inDays;

      if(difference_pulsion==0){
        difference_pulsion ="";
        prefix_pulsion ="Aujourd'hui";
      }else{
        prefix_pulsion ="jours";
      }

    });
  }

我也尝试了这段代码,没关系,当我调用该函数时,计时器增加了,但是我不想要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";
  }
}

1 个答案:

答案 0 :(得分:1)

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

使用dateTime.toIso8601String()和DateTime.parse()将使保存和加载变得不那么难看。 要计算经过的时间,可以使用DateTime.now()。difference(lastButtonPressed)

应该有一个格式化持续时间(https://api.flutter.dev/flutter/intl/DateFormat/formatDurationFrom.html)的函数,但尚未实现。我在这里找到一个:Formatting a Duration like HH:mm:ss

这是一个小例子:

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

为简单起见,我在全局范围的main方法中初始化了共享首选项。 Example