我有一个动画,其中两个容器相互碰撞。我希望容器以动画的方式回退到各自的起始偏移量。容器沿不同的路径和持续时间移动。
如动画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"),
)
],
),
),
);
}
}
我希望容器通过动画平滑地滑回到其各自的起始偏移。
答案 0 :(得分:1)
我会在这里添加一些说明,以帮助其他人。
颤动中的动画由AnimationController
控制。您可以使用单个AnimationController
控制一个或多个动画(如果要同时触发动画,则可以使用相同的控制器)。
现在,要启动动画(或链接到同一控制器的所有动画),可以使用forward()
方法。 forward()
方法接受一个参数,该参数指定动画应从哪个点继续播放,该参数值介于0 ... 1之间。
如果要向后制作动画,则控制器具有一个称为reverse()
的方法,该方法将以相反的顺序执行动画。同样,该方法接受的参数值为0到1,如果未指定任何参数,动画将从最后一个状态“反转”。
请注意,要制作反向动画,您应该不调用控制器上的reset()
。 reset()
方法会将控制器的所有值设置为初始值。