如何重新启动在完成前停止但具有不同参数的动画

blu*_*ile 2 dart flutter

我有一个动画,其中两个容器相互碰撞。我希望容器通过动画反转回它们各自的起始偏移量。容器沿着不同的路径和持续时间移动。

在此处输入图片说明

如动画 gif 所示,绿色和红色容器发生碰撞并跳回到它们的起始偏移量,而不是向后滑动。

这是我用来制作 GIF 的代码,在我的实际代码中,我使用矩形交叉来检查容器何时发生碰撞。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  List<AnimationController> _controller = List(2);
  List<Animation<Offset>> _animation = List(2);
  List<Tween<Offset>> 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 < 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(
      (_) => _afterLayout(),
    );
  }

  void _afterLayout() {
    for (int i = 0; i < 2; i++) {
      _controller[i].forward();
    }
  }

  @override
  void dispose() {
    super.dispose();
    for (int i = 0; i < 1; i++) {
      _controller[i].dispose();
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("collision"),
        ),
        body: Column(
          children: <Widget>[
            Expanded(
              child: Stack(
                children: <Widget>[
                  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"),
            )
          ],
        ),
      ),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望容器通过动画平滑地滑回各自的起始偏移量。

dan*_*ata 6

我会在这里添加一些解释以帮助其他人。

flutter 中的动画由AnimationController. 您可以使用单个控制一个或多个动画AnimationController(如果您想同时触发动画,您可以使用相同的控制器)。

现在,要启动动画(或链接到同一控制器的所有动画),您可以使用forward()方法。该forward()方法接受一个参数,该参数指定动画应从哪个点继续,参数值介于 0...1 之间。

如果你想倒着做动画,控制器有一个被调用的方法reverse(),它会以相反的顺序执行动画。同样,该方法接受一个值从 0 到 1 的参数,如果没有指定参数,动画将从上一个状态“反转”。

注意,为了有一个反向的动画,你应该reset()控制器上。reset()方法会将控制器的所有值设置为初始值。