【问题标题】:stopwatch and timer, problems with flutter秒表和计时器,颤振问题
【发布时间】:2021-05-17 06:46:34
【问题描述】:

我是飞镖和颤振的新手,目前我正在学习,所以请不要因为这个(也许)简单的问题而评判我。 我正在尝试构建一个计时器,但我所有的代码都是从秒表开始的,所以我想这是第一个问题。 简而言之,我正在尝试创建一个从 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";
  }
}

【问题讨论】:

    标签: flutter dart asynchronous timer stopwatch


    【解决方案1】:

    首先你需要考虑你是否总是想从 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')}";
    }
    

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

    【讨论】:

    • 所以,简而言之,现在我按照您的建议修改了代码,但有几件事不起作用:- 3 分钟显示为 elapsedTime 并且当我单击播放按钮时是静态的,- 当我播放暂停按钮它显示实际经过的秒数, - 当我单击重置按钮时,它给我“3:0”而不是“03:00”。我在下面发布了我的所有代码,以便您查看它
    • 也许我错了,但您更改了 startWatch 的实现:当您初始化计时器时,您不再引用 updateTimer 函数,而是使用 () 调用它。至于字符串的错误填充,您可以使用 toString().padLeft(2,'0') 分钟和秒。尝试进行这些更改。它现在应该可以按预期工作了
    • 嗨,Marco,这可能比我看起来更容易,但我不明白。我是一个完全的初学者,这个项目可能还不是我的水平,但是使用颤振为我的工作场所开发一些东西很有挑战性,所以我喜欢它。我不明白这个计时器是如何工作的,我应用了你建议的更改,但它仍然不起作用。我不明白哪里错了
    • 我已经编辑了我的答案,以便您全面了解您需要编写哪些内容才能使秒表正常工作
    【解决方案2】:

    这是修改后的代码:

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

    【讨论】:

      【解决方案3】:

      如果你想要一个带计时器的秒表,你可以使用我的简单 github 项目。 我希望这会对某人有所帮助。谢谢

      Here you can get my github repo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-07-22
        • 2019-11-16
        • 2019-07-03
        • 2022-01-01
        • 2019-03-13
        • 2021-05-27
        相关资源
        最近更新 更多