如何在手势点击时更改计时器的值?

How to change value of timer on gesture tap?

所以我 运行 我的计时器出现了另一个问题。

我有一个大小不一的盒子,当我点击它时,我希望计时器的值从 5 分钟更改为 15 分钟(或者最好,当我第一次点击时,它会从 5 分钟增加 > 10第二次敲击分钟,第三次敲击 15 分钟至 20 分钟,第四次敲击至 25 分钟) 要做到这一点,计时器应该处于非活动状态(用户只能在计时器不是 运行 时更改它)——但我 运行 遇到了“未定义名称 'isRunning' 的问题]."来自我在另一个小部件中的决赛

这是我的代码(也是附带问题,目前计时器只显示秒,我怎样才能让它显示实际的 5 分钟,如 5:00)

class timeryypage extends State<timerry> {
  static const maxSeconds = 5;
  int seconds = maxSeconds;
  Timer? timer;

  void resetTimer() => setState(() => seconds = maxSeconds);

  void startTimer({bool reset = true}) {
    if (reset) {
      resetTimer();
    }
    timer = Timer.periodic(Duration(seconds: 1), (_) {
      //add here instead seconds say minutes/miliseconds
      if (!mounted) // Putting this line of code with return under, fixed my issue i been having about mounted
        return;
      else if (seconds > 0) {
        setState(() => seconds--);
      } else {
        stopTimer(reset: false);
      }
    });
  }

  void stopTimer({bool reset = true}) {
    if (reset == mounted) {
      resetTimer();
    }
    setState(() => timer?.cancel());
  }

  @override
  Widget buildButtons() {
    final isRunning = timer == null ? false : timer!.isActive;
    final isCompleted = seconds == maxSeconds || seconds == 0;
    return isRunning || !isCompleted
        ? Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              ButtonWidget(
                text: isRunning ? "Pause" : "Resume",
                onClicked: () {
                  if (isRunning) {
                    stopTimer(reset: false);
                  } else {
                    startTimer(reset: false);
                  }
                },
              ),
              const SizedBox(width: 12),
              ButtonWidget(text: "Cancel", onClicked: stopTimer)
            ],
          )
        : ButtonWidget(
            text: "Start Timer!",
            color: Colors.black,
            backgroundColor: Colors.white,
            onClicked: () {
              startTimer();
            },
          );
  }

  Widget buildTimer() => SizedBox(
        width: 200,
        height: 200,
        child: Stack(
          fit: StackFit.expand,
          children: [
            CircularProgressIndicator(
              value: seconds / maxSeconds,
              //if you delete 1 - then it goes to other direction
              valueColor: AlwaysStoppedAnimation(Colors.white),
              strokeWidth: 12,
              backgroundColor: Colors.greenAccent,
            ),
            GestureDetector(
              behavior: HitTestBehavior.opaque,
              onTap: () {
                if (isRunning) {
                  print("do nothing");
                } else {
                  const snackBar = SnackBar(content: Text('Tap'));
                  ScaffoldMessenger.of(context).showSnackBar(snackBar);
                  print("tapped");
                  // later on i want to change timer from 5 minutes 10 minutes on first tap, then second tap to 15 minutes
                }
              },
              child: Center(child: buildTime()),
            ),
            //Center(child: buildTime()),
          ],
        ),
      );

  Widget buildTime() {
    if (seconds == 0) {
      return Icon(Icons.done, color: Colors.greenAccent, size: 112);
    } else {
      return Text(
        "$seconds",
        style: TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.white,
          fontSize: 80,
        ),
      );
    }
  }

非常感谢您的帮助!

编辑添加额外代码:

bool get isRunning => _timer?.isActive ?? false;
  int _seconds = 00;
  int _minutes = setminutes;
  static const setminutes = 25;
  Timer? _timer;
  var f = NumberFormat("00");

  void _stopTimer({bool reset = true}) {
    if (reset == true) {
      resetTimer();
    }
    setState(() => _timer?.cancel());
    ;
  }

  void resetTimer() => setState(() => _minutes = setminutes);

  void _startTimer({bool reset = true}) {
    if (reset) {
      resetTimer();
    }
    if (_timer != null) {
      _stopTimer();
    }
    if (_minutes > 0) {
      _seconds = _minutes * 60;
    }
    if (_seconds > 60) {
      _minutes = (_seconds / 60).floor();
      _seconds -= (_minutes * 60);
    }
    _timer = Timer.periodic(Duration(seconds: 1), (_) {
      if (!mounted)
        return;
      else if (_seconds > 0) {
        setState(() => _seconds--);
      }

      setState(() {
        if (_seconds > 0) {
          _seconds--;
        } else {
          if (_minutes > 0) {
            _seconds = 59;
            _minutes--;
          } else {
            _stopTimer(reset: false);
          }
        }
      });
    });
  }

  @override
  Widget buildButtons() {
    //final isRunning = timer == null ? false : timer!.isActive;
    final isCompleted = _minutes == setminutes || _seconds == 0;
    return isRunning || !isCompleted
        ? Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              ButtonWidget(
                text: isRunning ? "Pause" : "Resume",
                onClicked: () {
                  if (isRunning) {
                    _stopTimer(reset: false);
                  } else {
                    _startTimer(reset: false);
                  }
                },
              ),
              const SizedBox(width: 12),
              ButtonWidget(
                  text: "Cancel",
                  onClicked: () {
                    _stopTimer(reset: true);
                  })
            ],
          )
        : ButtonWidget(
            text: "Start Timer!",
            color: Colors.black,
            backgroundColor: Colors.white,
            onClicked: () {
              _startTimer();
            },
          );
  }

您的 buildTime 函数根据秒数创建一个 Text 小部件。如果您想以其他方式格式化它,您需要自己将秒数格式化为 String。例如:

var minutes = seconds ~/ 60;
var remainderSeconds = seconds % 60;
return Text('$minutes:${remainderSeconds.toString().padLeft(2, '0')}',
  ...);

另见:

  • Flutter/Dart - Format Duration to show just Minutes, Seconds and Milliseconds?