Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Listen for an animation to complete

I'm trying to perform an action after my animation finishes. I tried adding a statusListener but that is not working for me. My code looks like this:

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      duration: new Duration(milliseconds: 500),
      vsync: this,
    )..addStatusListener((AnimationStatus status) {
      print("Going");
      if (status.index == 3 && spins > 0) { // AnimationStatus index 3 == completed animation
        _controller.duration = new Duration(milliseconds: speed - 50);
        _controller.forward(from: _controller.value == null ? 0.0 : 1 - _controller.value);
        spins--;
        print(speed);
      }
    });
  }

The print(Going); never gets executed but my animation does end. What is going wrong?

///---Edit---///

I'm using an AnimatedBuilder, that part of the code looks like this:

child: new AnimatedBuilder(
  animation: _controller,
  child: new Image.network(widget.url),
  builder: (BuildContext context, Widget child) {
    return new Transform.rotate(
      angle: _controller.value * 2.0 * math.PI,
      child: child,
    );
  },
),
like image 452
Bram Vanbilsen Avatar asked Jul 26 '17 03:07

Bram Vanbilsen


2 Answers

Reacting to your comment and edit I looked into the AnimationBuilder. Adapting the example in the docs I came up with this working solution:

class Spinner extends StatefulWidget {
  @override
  _SpinnerState createState() => new _SpinnerState();
}

class _SpinnerState extends State<Spinner> with SingleTickerProviderStateMixin {
  AnimationController _controller;
  CurvedAnimation _animation;

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      duration: const Duration(seconds: 5),
      vsync: this,
    )..forward();

    _animation = new CurvedAnimation(
        parent: _controller,
        curve: Curves.linear,
    )..addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed)
        print('completed');
    });
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new AnimatedBuilder(
      animation: _animation,
      child: new Container(width: 200.0, height: 200.0, color: Colors.green),
      builder: (BuildContext context, Widget child) {
        return new Transform.rotate(
          angle: _controller.value * 2.0 * 3.1415,
          child: child,
        );
      },
    );
  }
}

As you can see, I used the controller as parent to an animation, which was than used as animation for the AnimationBuilder. Hope it helps.

like image 120
Rainer Wittmann Avatar answered Sep 27 '22 20:09

Rainer Wittmann


You can also use the whenComplete listener

_animationController.forward().whenComplete((){
     //Trigger different responses, when animation is started at different places.
})
like image 26
ChinLoong Avatar answered Sep 27 '22 19:09

ChinLoong