flutter 快速按下计时器上的播放/暂停按钮会使计时器倒计时的速度增加两倍,想知道如何修复逻辑

clj7thdc  于 2023-02-13  发布在  Flutter
关注(0)|答案(1)|浏览(143)

我有一个简单的倒计时文本,可以通过按钮暂停/播放。它从传递给小工具的秒数开始倒计时。我的问题是,当我快速按下暂停/播放按钮时,计时器开始倒计时的速度更快。我猜这是因为toggleTimer当按钮被多次按下时运行的()方法触发了定时器周期函数的两个示例。我如何修改这个逻辑?

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:quickrest/styles/text_styles.dart';
import 'package:quickrest/styles/color_styles.dart';
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';

class ActiveTimerScreen extends StatefulWidget {
  const ActiveTimerScreen({super.key, required this.seconds});

  final int seconds;

  @override
  State<ActiveTimerScreen> createState() => _ActiveTimerScreenState();
}

class _ActiveTimerScreenState extends State<ActiveTimerScreen> {
  int _timeLeft = 0;
  bool timerStarted = false;

  @override
  void initState() {
    super.initState();
    _timeLeft = widget.seconds;
    /// Have timer start by default.
    timerStarted = true;
    toggleTimer();
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: SafeArea(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            const SizedBox(width: double.infinity),
            Padding(
              padding: EdgeInsets.only(
                top: MediaQuery.of(context).size.height * 0.3,
              ),
              child: Text(
                '${_timeLeft ~/ 60} : ${(_timeLeft % 60).toString().padLeft(2, '0')}',
                style: activeTimerTitleTextStyle,
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(
                top: 80.0,
              ),
              child: ElevatedButton(
                style: ElevatedButton.styleFrom(
                  shape: const CircleBorder(),
                  backgroundColor: Colors.black,
                ),
                onPressed: () {
                  setState(() {
                    if (timerStarted) {
                      timerStarted = false;
                    } else {
                      timerStarted = true;
                      toggleTimer();
                    }
                  });
                },
                child: Padding(
                  padding: const EdgeInsets.all(4.0),
                  child: Icon(
                    !timerStarted ? Icons.play_arrow : Icons.pause,
                    size: 100,
                  ),
                ),
              ),
            ),
            Padding(
              padding: const EdgeInsets.only(top: 80.0),
              child: OutlinedButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                style: OutlinedButton.styleFrom(
                  backgroundColor: Colors.white,
                  side: const BorderSide(
                    color: Colors.white,
                  ),
                  shape: const RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(
                      Radius.circular(24),
                    ),
                  ),
                ),
                child: const Text(
                  "Cancel",
                  style: activeTimerCancelTextStyle,
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  void toggleTimer() {
    const oneSec = Duration(seconds: 1);
    Timer.periodic(oneSec, (Timer t) {
      if (_timeLeft < 1 || timerStarted == false) {
        t.cancel();
      } else {
        setState(() {
          _timeLeft = _timeLeft - 1;
        });
      }
    });
  }
}
ffscu2ro

ffscu2ro1#

您正在启动不同的计时器,然后每秒独立执行多次:

_timeLeft = _timeLeft - 1;

如果在_ActiveTimerScreenState中添加

Timer? _timer;

然后你的toggleTimer方法应该看起来像这样:

void toggleTimer() {
    const oneSec = Duration(seconds: 1);
    _timer?.cancel();
    _timer = Timer.periodic(oneSec, (Timer t) {
      if (_timeLeft < 1) {
        t.cancel();
      } else {
        setState(() {
          _timeLeft = _timeLeft - 1;
        });
      }
    });
  }

它不会启动不同的计时器。
而且,实际上您并没有使用toggleTimer来切换;您只使用它来启动新的计时器(您只在timerStarted为false时调用它)。您可能希望将它重命名为类似launchNewTimer的名称。您还可以在按下按钮时停止/取消旧的计时器:

onPressed: () {
                  setState(() {
                    if (timerStarted) {
                      timerStarted = false;
                      _timer?.cancel();
                    } else {
                      timerStarted = true;
                      toggleTimer();
                    }
                  });

相关问题