How to play different animations when a button is tapped depending on the current state?

Advertisements

I have a widget that is using a GestureDetector and AnimatedBuilder to play an animation when the button is tapped. I can play a single animation without issue. What I want to do is be able to play three different animations on the button (different colors, different duration) depending on the state. Ex;

  • If State = A, play animation A

  • If State = B, play animation B

  • If State = C, play animation C

I have tried using three AnimationControllers and I can’t seem to get it working. How can I accomplish this? Is the solution three AnimationControllers? Is it one AnimationController with multiple TweenSequences? Is it one TweenSequence that I add and remove Tweens from?

Thank you for your time.

>Solution :

As I had one implementation, I’m attaching that here

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  TweenSequence<Color> _tweenSeqA;
  TweenSequence<Color> _tweenSeqB;
  TweenSequence<Color> _tweenSeqC;
  TweenSequence<Color> _currentTweenSeq;

  String _currentState = 'A';

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 500),
    );

    _tweenSeqA = TweenSequence<Color>(
      [
        TweenSequenceItem(
          tween: ColorTween(begin: Colors.red, end: Colors.yellow),
          weight: 1,
        ),
      ],
    );

    _tweenSeqB = TweenSequence<Color>(
      [
        TweenSequenceItem(
          tween: ColorTween(begin: Colors.green, end: Colors.blue),
          weight: 1,
        ),
      ],
    );

    _tweenSeqC = TweenSequence<Color>(
      [
        TweenSequenceItem(
          tween: ColorTween(begin: Colors.yellow, end: Colors.pink),
          weight: 1,
        ),
      ],
    );

    _currentTweenSeq = _tweenSeqA;
  }

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

  void _playAnimation() {
    _currentTweenSeq = _getTweenSequenceForCurrentState();

    _controller
      ..reset()
      ..animateTo(
        1,
        curve: Curves.linear,
      );
  }

  TweenSequence<Color> _getTweenSequenceForCurrentState() {
    switch (_currentState) {
      case 'A':
        return _tweenSeqA;
      case 'B':
        return _tweenSeqB;
      case 'C':
        return _tweenSeqC;
      default:
        return _tweenSeqA;
    }
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          if (_currentState == 'A') {
            _currentState = 'B';
          } else if (_currentState == 'B') {
            _currentState = 'C';
          } else {
            _currentState = 'A';
          }
        });

        _playAnimation();
      },
      child: AnimatedBuilder(
        animation: _controller,
        builder: (context, child) {
          final color = _currentTweenSeq.evaluate(_controller);

          return Container(
            width: 100,
            height: 100,
            color: color,
          );
        },
      ),
    );
  }
}

In this illustration, three TweenSequenceColor> objects—one for each state—are defined. In order to maintain track of the TweenSequence being used for the animation, we additionally define a variable called _currentTweenSeq.

If you still have some confusion then add your valuable comment.

Leave a Reply Cancel reply