Search code examples
flutterflutter-animation

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


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.