Flutter: how to detect if animation has been paused/stopped

113 Views Asked by At

This may sound simple but I'm referring about checking it after calling stop(). For example:

if (timerControllerList[index].isAnimating) {
   await timerControllerList[index].stop();
}

if (timerControllerList[index].status == AnimationStatus.forward) {
  // it goes in  :(
}

I have 2 timer animations (that's why I have a List with them) that I can pause independently before reaching 10 seconds and I need to detect when pausing any of them, that the other is also stopped. In this case all of them have a status forward.

Initialization:

void initTimer(int index) {
// called from initState()

    late AnimationController timerController;
    late Animation<int> timerAnimation;
    int timerCounter = 10;

    timerController = AnimationController(
      vsync: this,
      duration: Duration(seconds: timerCounter),
    );

    timerAnimation =
        StepTween(begin: 0, end: timerCounter * 1000).animate(timerController)
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              stopTimer(index);
            }
          });

    timerControllerList.add(timerController);
    timerAnimationList.add(timerAnimation);
  }
3

There are 3 best solutions below

0
On BEST ANSWER

My problem came from another async animation:

void stopTimer(int index) async {
    if (countDownController.isAnimating || !playingGame) return;

    // stopping timer
    if (timerControllerList[index].isAnimating) {
      timerControllerList[index].stop();
    }

    // timer finished
    blackBGControllerList[index].reset();
    await finalMsgControllerList[index].forward();
    await calculateFinalMsg(index);
    if (players == 1) {
      playAgainButtonController.forward();
      playingGame = false;
      saveBestScore(index);
    } else {
      bool someoneCounting =
          timerControllerList.any((controller) => controller.isAnimating);
      if (someoneCounting) return;
      playingGame = false;
      findWinner();
    }
  }

In timerControllerList[index].stop(); is where I was stopping my first animation but await finalMsgControllerList[index].forward() was initiating another one.

So if I clicked before finishing that second animation, it was creating the issue. Not sure why because the stop/check is running before but removing the await fixed my issue.

0
On

You could use listeners to help you with that. This would check if it is stopped:

_animation.addStatusListener((status) {
    if (status == AnimationStatus.dismissed) {
        // stopped
    }

or to check if it is paused something like this:

_controller.addListener(() {
if (_controller.isAnimating == false) {
    // paused
}

or even:

_animation.addStatusListener((status) {
    if (status == AnimationStatus.forward || 
        status == AnimationStatus.reverse) {
        // running
    } else {
        // paused
    }
});
1
On

This is how I check the status of an animation on my splash screen.

    _animation = Tween<double>(begin: 0, end: 1).animate(_controller)
      ..addStatusListener(
        (status) {
          if (status == AnimationStatus.completed) {
            _controller.reverse().then(
                  (value) => Navigator.pushAndRemoveUntil(
                      context,
                      MaterialPageRoute(
                        builder: (context) => const FirebaseAuthCheck(),
                      ),
                      (route) => false),
                );
          }
        },
      );