秒表和计时器,颤振问题

时间:2021-02-13 21:31:04

标签: flutter dart asynchronous timer stopwatch

我是 dart 和 flutter 的新手,目前我正在学习,所以请不要因为这个(也许)简单的问题而评判我。 我正在尝试构建一个计时器,但我所有的代码都是从秒表开始的,所以我想这是第一个问题。 简而言之,我试图从 3 分钟开始创建一个计时器,我可以随时停止和启动它(它假设是一个裁判工具),但我的起始字符串是“03:00”,我可以看到,所以没关系,我找不到任何关于时间如何从 03:00 到 00:00 的答案。 另外,正如您在我的代码中看到的,我创建了一个按钮来重置时间,但它总是回到 00:00 而不是 03:00。 任何人都可以提供帮助?我肯定错过了什么。

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

class NewStopWatch extends StatefulWidget {
  @override
  _NewStopWatchState createState() => _NewStopWatchState();
}

class _NewStopWatchState extends State<NewStopWatch> {
  Stopwatch watch = Stopwatch();
  Timer timer;
  bool startStop = true;

  IconData btnPlayStatus = Icons.play_arrow;

  String elapsedTime = '03:00';

  updateTime(Timer timer) {
    if (watch.isRunning) {
      setState(() {
        elapsedTime = transformMilliSeconds(watch.elapsedMilliseconds);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20.0),
      child: Column(
        children: <Widget>[
          Text(elapsedTime, style: TextStyle(fontSize: 60.0)),
          SizedBox(height: 20.0),
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: 100,
                height: 50,
                child: FloatingActionButton(
                    shape: ContinuousRectangleBorder(),
                    heroTag: "btn1",
                    backgroundColor: Colors.blueGrey,
                    onPressed: () => startOrStop(),
                    child: Icon(btnPlayStatus)),
              ),
              SizedBox(width: 20.0),
              Container(
                width: 30,
                height: 50,
                child: FloatingActionButton(
                  shape: ContinuousRectangleBorder(),
                    heroTag: "btn2",
                    backgroundColor: Colors.blueGrey,
                    onPressed: () => resetWatch(), //resetWatch,
                    child: Icon(Icons.subdirectory_arrow_left)),
              ),
            ],
          )
        ],
      ),
    );
  }

  resetWatch() {
    setState(() {
      watch.reset();
      setTime();
    });
  }

  startOrStop() {
    if(startStop) {
      setState(() {
        btnPlayStatus = Icons.pause;
      });
      startWatch();
    } else {
      setState(() {
        btnPlayStatus = Icons.play_arrow;
      });
      stopWatch();
    }
  }

  startWatch() {
    setState(() {
      startStop = false;
      watch.start();
      timer = Timer.periodic(Duration(milliseconds: 100), updateTime);
    });
  }

  stopWatch() {
    setState(() {
      startStop = true;
      watch.stop();
      setTime();
    });
  }

  setTime() {
    var timeSoFar = watch.elapsedMilliseconds;
    setState(() {
      elapsedTime = transformMilliSeconds(timeSoFar);
    });
  }

  transformMilliSeconds(int milliseconds) {
    int hundreds = (milliseconds / 10).truncate();
    int seconds = (hundreds / 100).truncate();
    int minutes = (seconds / 60).truncate();

    String minutesStr = (minutes % 60).toString().padLeft(2, '0');
    String secondsStr = (seconds % 60).toString().padLeft(2, '0');

    return "$minutesStr:$secondsStr";
  }
}

2 个答案:

答案 0 :(得分:0)

首先你要考虑是否总是要从3分钟开始;如果是这样,请创建一个静态字段,如下所示:

static duration = new Duration(minutes:3);

编辑:我重构了您的代码并使其正常工作。

updateTimer(Timer t) {
    if (watch.isRunning) {
      setState(() {
        Duration newDuration = _NewStopWatchState.duration -
            new Duration(milliseconds: watch.elapsedMilliseconds);
        elapsedTime = durationToMinutesAndSeconds(newDuration);
      });
    }
}

这是updateTimer 函数。 接下来,您没有更新 stopWatch() 函数来处理新更改,所以我为您更改了它。

stopWatch() {
    setState(() {
      startStop = true;
      watch.stop();
      Duration newDuration = _NewStopWatchState.duration -
          new Duration(milliseconds: watch.elapsedMilliseconds);
      elapsedTime = durationToMinutesAndSeconds(newDuration);
    });
}

我还更新了 resetWatch() 函数

resetWatch() {
    setState(() {
      watch.reset();
      elapsedTime = durationToMinutesAndSeconds(_NewStopWatchState.duration);
    });
}

我还创建了一个实用函数来将持续时间转换为分钟和秒。

String durationToMinutesAndSeconds(Duration d) {
    return "${d.inMinutes.toString().padLeft(2, '0')}" +
            ":${d.inSeconds.remainder(60).toString().padLeft(2, '0')}";
}

我已经在我的机器上试过了,代码运行正常,希望这次即使在你这边也能正常工作。

答案 1 :(得分:0)

修改后的代码:

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

class NewStopWatch extends StatefulWidget {
  @override
  _NewStopWatchState createState() => _NewStopWatchState();
}

class _NewStopWatchState extends State<NewStopWatch> {
  Stopwatch watch = Stopwatch();
  Timer timer;
  bool startStop = true;
  static Duration duration = Duration(minutes:3);

  IconData btnPlayStatus = Icons.play_arrow;

  String elapsedTime = '';

  updateTimer() {
    if (watch.isRunning) {
      setState(() {
        elapsedTime = transformMilliSeconds(_NewStopWatchState.duration.inMilliseconds - watch.elapsedMilliseconds);
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.all(20.0),
      child: Column(
        children: <Widget>[
          Text(elapsedTime),
          SizedBox(height: 20.0),
          Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: 100,
                height: 50,
                child: FloatingActionButton(
                    shape: ContinuousRectangleBorder(),
                    heroTag: "btn1",
                    backgroundColor: Colors.blueGrey,
                    onPressed: () => startOrStop(),
                    child: Icon(btnPlayStatus)),
              ),
              SizedBox(width: 20.0),
              Container(
                width: 30,
                height: 50,
                child: FloatingActionButton(
                  shape: ContinuousRectangleBorder(),
                    heroTag: "btn2",
                    backgroundColor: Colors.blueGrey,
                    onPressed: () => resetWatch(), //resetWatch,
                    child: Icon(Icons.subdirectory_arrow_left)),
              ),
            ],
          ),
        ],
      ),
    );
  }

  resetWatch() {
    setState(() {
      watch.reset();
      setTime();
      elapsedTime="${_NewStopWatchState.duration
          .inMinutes}:${_NewStopWatchState.duration.inSeconds.remainder(60)}";
    });
  }

  startOrStop() {
    if(startStop) {
      setState(() {
        btnPlayStatus = Icons.pause;
      });
      startWatch();
    } else {
      setState(() {
        btnPlayStatus = Icons.play_arrow;
      });
      stopWatch();
    }
  }

  startWatch() {
    setState(() {
      startStop = false;
      watch.start();
      timer = Timer.periodic(Duration(milliseconds: 100), updateTimer());
    });
  }

  stopWatch() {
    setState(() {
      startStop = true;
      watch.stop();
      setTime();
    });
  }

  setTime() {
    var timeSoFar = watch.elapsedMilliseconds;
    setState(() {
      elapsedTime = transformMilliSeconds(timeSoFar);
    });
  }

  transformMilliSeconds(int milliseconds) {
    int hundreds = (milliseconds / 10).truncate();
    int seconds = (hundreds / 100).truncate();
    int minutes = (seconds / 60).truncate();

    String minutesStr = (minutes % 60).toString().padLeft(2, '0');
    String secondsStr = (seconds % 60).toString().padLeft(2, '0');

    return "$minutesStr:$secondsStr";
  }
}
相关问题