flutteranimationdartvsyncanimationcontroller

How I do make my animation repeat when I click on it with animatedbuilder? flutter/dart


I'm working on a custom animation button. I want to repeat the animation every time the user taps on it. So when the user clicks on it, the container scales bigger. And returns to the normal size. And when the user clicks on it again it does it again. Right now the animation just scales up to the defined sized and stops. It doesn't do anything after that.

class CustomAnimation extends StatefulWidget {
  @override
  _CustomAnimationState createState() => _CustomAnimationState();
}

class _CustomAnimationState extends State<CustomAnimation> with SingleTickerProviderStateMixin {

  AnimationController _controller;

  @override
  void initState() {
    // TODO: implement initState

    _controller = AnimationController(
      vsync: this,
      duration: Duration(seconds: 2),
    );
    _controller.addListener(() {
      setState(() {
        //do something
      });
    });
    _controller.forward();
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedBuilder(
          animation: _controller.view,
          builder: (context,child){
            return Transform.scale(scale: _controller.value *.9,
                child: Container(
                  width: 200,
                  height: 200,
                  color: Colors.lightGreen[200],
                  child: Center(
                    child: Text('Animation test'),
                  ),
                ),
            );
          },
        ),

      )
    );
  }
}

Solution

  • You can copy paste run full code below
    You can listen AnimationStatus.completed and call _controller.reverse()
    And use InkWell call _controller.forward();

     animation = Tween<double>(begin: 1.0, end: 1.2).animate(_controller)
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              _controller.reverse();
            }
          });
    ...   
    return Transform.scale(
                scale: animation.value,
                child: InkWell(
                  onTap: () {
                    _controller.forward();
                  },      
    

    working demo

    enter image description here

    full code

    import 'package:flutter/material.dart';
    
    class CustomAnimation extends StatefulWidget {
      @override
      _CustomAnimationState createState() => _CustomAnimationState();
    }
    
    class _CustomAnimationState extends State<CustomAnimation>
        with SingleTickerProviderStateMixin {
      AnimationController _controller;
      Animation<double> animation;
    
      @override
      void initState() {
        _controller =
            AnimationController(vsync: this, duration: Duration(seconds: 2));
        _controller.addListener(() {
          setState(() {
            //do something
          });
        });
    
        _controller.forward();
        animation = Tween<double>(begin: 1.0, end: 1.2).animate(_controller)
          ..addStatusListener((status) {
            if (status == AnimationStatus.completed) {
              _controller.reverse();
            }
          });
        super.initState();
      }
    
      @override
      void dispose() {
        _controller.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            body: Center(
              child: AnimatedBuilder(
                animation: animation,
                builder: (context, child) {
                  return Transform.scale(
                    scale: animation.value,
                    child: InkWell(
                      onTap: () {
                        _controller.forward();
                      },
                      child: Container(
                        width: 200,
                        height: 200,
                        color: Colors.lightGreen[200],
                        child: Center(
                          child: Text('Animation test'),
                        ),
                      ),
                    ),
                  );
                },
              ),
            ));
      }
    }
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
            visualDensity: VisualDensity.adaptivePlatformDensity,
          ),
          home: CustomAnimation(),
        );
      }
    }