title: How to restart an animation stopped before completion but with different parameters
body: <p>I have an animation where two containers collide with each other. I want the containers to reverse back with animation to their respective starting offset. The containers move along varied paths and duration. </p>
  
  <p><a href="https://i.stack.imgur.com/6QcTn.gif" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6QcTn.gif" alt="enter image description here"></a></p>
  
  <p>As seen in the animation gif attached the green and red containers collide and jump back to their starting offsets rather than sliding back.</p>
  
  <p>Here is the code I used to make the GIF, in my actual code I'm using rectangle intersection to check when the containers collide.</p>
  
  <pre class="lang-dart prettyprint-override"><code>import 'package:flutter/material.dart';
  
  void main() {
    runApp(MyApp());
  }
  
  class MyApp extends StatefulWidget {
    @override
    _MyAppState createState() =&gt; _MyAppState();
  }
  
  class _MyAppState extends State&lt;MyApp&gt; with TickerProviderStateMixin {
    List&lt;AnimationController&gt; _controller = List(2);
    List&lt;Animation&lt;Offset&gt;&gt; _animation = List(2);
    List&lt;Tween&lt;Offset&gt;&gt; tween = List(2);
  
    @override
    void initState() {
      super.initState();
      tween[0] = Tween(begin: Offset(0, 10), end: Offset(200, 10));
      tween[1] = Tween(begin: Offset(200, 10), end: Offset(0, 10));
      for (int i = 0; i &lt; 2; i++) {
        _controller[i] =
            AnimationController(vsync: this, duration: Duration(seconds: 1));
  
        _animation[i] = tween[i].animate(_controller[i])
          ..addListener(
            () {
              setState(
                () {
                  print(
                      '${_animation[0].value.dx.toInt()}:${_animation[0].value.dy.toInt()} ${_animation[1].value.dx.toInt()}:${_animation[1].value.dy.toInt()}');
                  if (((_animation[0].value.dx) / 2).round() ==
                      ((_animation[1].value.dx) / 2).round()) {
                    _controller[0].stop();
                    _controller[1].stop();
  
                    _controller[0].reset();
                    _controller[1].reset();
  
                    Future.delayed(Duration(milliseconds: 100)).then((_) {
                      tween[0] = Tween(
                          begin: Offset(
                              _animation[0].value.dx, _animation[0].value.dy),
                          end: Offset(0, 10));
                      tween[1] = Tween(
                          begin: Offset(
                              _animation[1].value.dx, _animation[1].value.dy),
                          end: Offset(200, 10));
  
                      _animation[0] = tween[0].animate(_controller[0]);
                      _animation[1] = tween[1].animate(_controller[1]);
  
                      _controller[0].forward();
                      _controller[1].forward();
                    });
                  }
                },
              );
            },
          );
      }
  
      WidgetsBinding.instance.addPostFrameCallback(
        (_) =&gt; _afterLayout(),
      );
    }
  
    void _afterLayout() {
      for (int i = 0; i &lt; 2; i++) {
        _controller[i].forward();
      }
    }
  
    @override
    void dispose() {
      super.dispose();
      for (int i = 0; i &lt; 1; i++) {
        _controller[i].dispose();
      }
    }
  
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        home: Scaffold(
          appBar: AppBar(
            title: Text("collision"),
          ),
          body: Column(
            children: &lt;Widget&gt;[
              Expanded(
                child: Stack(
                  children: &lt;Widget&gt;[
                    Container(
                      width: double.infinity,
                      height: double.infinity,
                    ),
                    Positioned(
                      left: _animation[0] != null ? _animation[0].value.dx : 0,
                      top: _animation[0] != null ? _animation[0].value.dy : 0,
                      child: Container(
                        width: 50,
                        height: 50,
                        color: Colors.red,
                      ),
                    ),
                    Positioned(
                      left: _animation[1] != null ? _animation[1].value.dx : 0,
                      top: _animation[1] != null ? _animation[1].value.dy : 0,
                      child: Container(
                        width: 50,
                        height: 50,
                        color: Colors.green,
                      ),
                    ),
                  ],
                ),
              ),
              RaisedButton(
                onPressed: () {
                  _controller[0].reset();
                  _controller[1].reset();
  
                  tween[0] = Tween(begin: Offset(0, 10), end: Offset(200, 10));
                  tween[1] = Tween(begin: Offset(200, 10), end: Offset(0, 10));
  
                  _controller[0].duration = Duration(seconds: 1);
                  _controller[1].duration = Duration(seconds: 1);
  
                  _animation[0] = tween[0].animate(_controller[0]);
                  _animation[1] = tween[1].animate(_controller[1]);
  
                  _controller[0].forward();
                  _controller[1].forward();
                },
                child: Text("Animate"),
              )
            ],
          ),
        ),
      );
    }
  }
  </code></pre>
  
  <p>I want the containers to smoothly slide back to their respective starting offsets with animation.</p>