flutter - 如何在颤动中启动间隔动画
问题描述
我想制作三个落在屏幕上的球的动画。但我希望第一个球的动画比第二个球的动画开始得早,第二个球的动画比第三个球的动画开始得早一点。
我试图在动画的前进之间给予某种超时,但由于某种原因没有奏效。在下面的代码中,我为三个球完成了相同的动画。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController animationController1,
animationController2,
animationController3;
Animation<double> animation, animation2, animation3;
@override
void initState() {
animationController1 =
AnimationController(duration: Duration(milliseconds: 300), vsync: this);
animationController2 =
AnimationController(duration: Duration(milliseconds: 300), vsync: this);
animationController3 =
AnimationController(duration: Duration(milliseconds: 300), vsync: this);
animation = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController1, curve: Interval(0.0, 1.0)),
);
animation2 = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController2, curve: Interval(1.0, 2.0)),
);
animation3 = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController3, curve: Interval(2.0, 3.0)),
);
animationController1.addListener(() {
print('1 ${animation.value}');
print('2 ${animation.value}');
print('3 ${animation.value}');
setState(() {});
});
animationController1.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController1.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController1.forward();
}
});
animationController2.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController2.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController2.forward();
}
});
animationController3.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController3.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController3.forward();
}
});
animationController1.forward();
animationController2.forward();
animationController3.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildBallOne(),
SizedBox(
width: 6.0,
),
buildBallTwo(),
SizedBox(
width: 6.0,
),
buildBallThree()
],
),
),
),
),
);
}
Widget buildBallOne() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController1.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
Widget buildBallTwo() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController2.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
Widget buildBallThree() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController3.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
}
解决方案
那是因为您同时运行所有控制器。
我只是增加了延迟并做了一些曲调。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
AnimationController animationController1, animationController2, animationController3;
Animation<double> animation1, animation2, animation3;
@override
void initState() {
animationController1 = AnimationController(
duration: Duration(milliseconds: 600),
vsync: this,
);
animationController2 = AnimationController(
duration: Duration(milliseconds: 600),
vsync: this,
);
animationController3 = AnimationController(
duration: Duration(milliseconds: 600),
vsync: this,
);
animation1 = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController1, curve: Interval(0.0, 1.0)),
);
animation2 = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController2, curve: Interval(0.0, 1.0)),
);
animation3 = Tween(
begin: 0.0,
end: 1.0,
).animate(
CurvedAnimation(parent: animationController3, curve: Interval(0.0, 1.0)),
);
animationController1.addListener(() {
print('1 ${animation1?.value}');
print('2 ${animation2?.value}');
print('3 ${animation3?.value}');
setState(() {});
});
animationController1.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController1.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController1.forward();
}
});
animationController2.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController2.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController2.forward();
}
});
animationController3.addStatusListener((status) {
if (status == AnimationStatus.completed) {
animationController3.reverse();
} else if (status == AnimationStatus.dismissed) {
animationController3.forward();
}
});
Future.delayed(
Duration(milliseconds: 300),
() => animationController1.forward(),
);
Future.delayed(
Duration(milliseconds: 600),
() => animationController2.forward(),
);
Future.delayed(
Duration(milliseconds: 900),
() => animationController3.forward(),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Container(
child: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
buildBallOne(),
SizedBox(
width: 6.0,
),
buildBallTwo(),
SizedBox(
width: 6.0,
),
buildBallThree()
],
),
),
),
),
);
}
Widget buildBallOne() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController1.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
Widget buildBallTwo() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController2.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
Widget buildBallThree() {
return Container(
margin: EdgeInsets.only(top: 100 - (animationController3.value * 50)),
width: 35,
height: 35,
decoration: ShapeDecoration(
shape: CircleBorder(),
color: Colors.blue,
),
);
}
}
实际上,因为所有球的动画路径都相同,所以您可以使用一个控制器并为每个球计算不同的位置
ps使用Animated Widget或AnimatedBuilder,不触发setState刷新页面,会提供更好的性能。
推荐阅读
- angular - 从 Angular 10 访问时在 Hasura Graphql 上遇到 CORS 问题
- linux - 只有一组 shell 脚本应该执行一个 shell 脚本
- java - 房间数据库中更新的重复数据条目
- laravel - laravel 电子邮件验证 mailtrap 在 localhost 上有效,但在 ubuntu 服务器 digitalocean 上无效
- r - 从 R 中的递归函数编译向量
- php - 在 Symfony 3.4 中找不到模板错误
- python - 为什么我不能在 heroku 上部署 react flask 应用程序?
- slack-api - 如何更改 Slack 中的模态图标?
- python - 在 pandas 数据框中查找事件的每个 id 的连续天数
- javascript - 在 useState 中更新 Map 时避免重新渲染组件