I am having some problems with an animation I'm trying to do in Flutter using Dart. I am trying to incrementally increase the height of a box when the user clicks a button. Below is a very simple example of what I am trying to achieve. My problem is that the smooth animation only works for the first click but after that there is no animation, the box only gets larger. Is there a way to fix this problem?

import 'package:flutter/material.dart';

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: MyHomePage(title: 'Size Animation'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  double _myHeight = 310;
  double _counter = 30;
  double _target = 10;

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

    _animationController =
        AnimationController(vsync: this, duration: Duration(seconds: 1));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          alignment: Alignment.center,
          child: Column(
            children: <Widget>[
              FlatButton(
                child: Text('Reset me'),
                color: Colors.red,
                onPressed: () {
                  _target = 10;
                  _animationController.reset();
                },
              ),
              FlatButton(
                child: Text('Click me'),
                color: Colors.blue,
                onPressed: () {
                  if (_target < _myHeight) {
                    setState(() {
                      _target += _counter;
                    });
                  }
                  _animationController.forward();
                },
              ),
              AnimatedBuilder(
                  animation: _animationController,
                  builder: (context, child) {
                    return Container(
                      color: Colors.green,
                      width: 80,
                      height: _animationController.value * _target,
                    );
                  }),
            ],
          ),
        ),
      ),
    );
  }
}


Solution 1: Leo Letto

You can easily reach this just by having a simple AnimatedContainer, that will automatically animate itself whenever one of it's proprierties changes, so your widget would look like this:

AnimatedContainer(
   duration: const Duration(seconds: 1),
   color: Colors.green,
   width: 80,
   height: _target
)

That way when _target value changes with setState value, your widget would animate the height.

Your current animation is working only the first time, because actually your are just running the animationController only once, then you recall the forward() again and again, but your animation has already been animated so, there's no forward, the value is going from 0 to 1 only the first time, then everytime you call the forward() method the animation is already at value 1, so you see no animation. One way you could do that if you really wanna keep this animation with an AnimatedBuilder you should give it a Tween instead of your animationController