Flutter中的基本动画
虽然 Flutter 有大量用于为您的应用程序创建动画效果的令人惊叹的包,但也有用于手动创建更精细动画的内置方法。
先决条件
对于我们的跨屏动画,我假设您已经知道如何创建基本路线,只是为了保持简短。 如果您对此不满意,可以在此处查看 文档 。
线性动画
我们动画的主要三个部分是 ticker 来控制我们的时间,controller 来注册我们的参数,比如我们的持续时间,然后我们想要更改的值。 在我们的小部件被渲染之前,在我们的 initState 中,我们可以将我们的控制器设置为它的参数,设置它的方向,并添加一个侦听器来在每次更改时重置我们的小部件状态。
默认情况下,控制器会在我们设置的持续时间内将变化从 0 移动到 1,我们可以在监听器中打印 controller.value 来观察这种情况。 我们可以通过设置 upperBound 或 lowerBound 属性来更改我们的默认开始和结束值。
主要.dart
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this); // Links this controller to this widget so it won't run if the parent widget isn't rendered, to save on resources.
controller.forward();
controller.addListener(() => setState(() {}));
}
}
要使用我们的动画,我们只需将我们想要的任何内容(例如不透明度)设置为 controller.value。
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Opacity(
opacity: controller.value,
child: Container(width: 50, height: 50, color: Colors.red),
),
),
);
}
曲线动画
我们可以使用不同的曲线变化来精确控制控制器的变化方式,而不是无聊的线性动画。 为此,我们可以使用 CurvedAnimation 在我们原来的控制器上创建一种包装器。 这个包装器将采用它的父级、我们的控制器和我们想要应用的曲线。 当使用弯曲动画时,除了 0 和 1 之外,我们不能有下限和上限,所以当我们应用它时,我们可以乘以它的值。 在 文档 中有一个非常广泛的选项列表。
controller 上的另一个有用方法是 addStatusListener,这将允许我们利用它的生命周期。 只要它的值达到其上限或下限,我们的控制器就会触发完成或解除事件。 我们可以使用它的 forward 和 reverse 方法来无限循环我们的动画。
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
void initState() {
super.initState();
controller = AnimationController(
duration: Duration(seconds: 1),
vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: Colors.red),
),
);
}
}
补间
除了使用数字值之外,我们还可以使用补间(介于之间的缩写)来处理其他事物的范围,例如颜色。 就像我们的曲线动画一样,它将充当控制器或动画的包装器,我们可以将颜色设置为其值。
主要.dart
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController controller;
Animation animation;
Animation changeColor;
void initState() {
super.initState();
controller =
AnimationController(duration: Duration(seconds: 1), vsync: this);
animation = CurvedAnimation(parent: controller, curve: Curves.slowMiddle);
changeColor = ColorTween(begin: Colors.red, end: Colors.blue).animate(animation);
controller.forward();
animation.addListener(() => setState(() {}));
controller.addStatusListener((status) {
if (status == AnimationStatus.completed) controller.reverse(from: 400);
else if (status == AnimationStatus.dismissed) controller.forward();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.only(bottom: animation.value * 400),
width: 50,
height: 50,
color: changeColor.value),
),
);
}
}
十字屏
当我们想要在不同屏幕上的小部件之间进行转换时,另一个很棒的技术是使用 Hero 小部件。 我们只需要用匹配的标签将每个都包装在自己的 Hero 小部件中。 标签必须是唯一的,并且任何时候屏幕上都不能有多个。
第一屏
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Hero(tag: 'icon', child: Icon(Icons.add)),
]),
Navbar()
]));
}
第二屏
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SizedBox(width: 1),
Hero(
tag: 'icon',
child: Icon(Icons.add, color: Colors.red, size: 75)),
]),
Navbar()
]),
);
}
结论
在过去的大多数前端 Web 技术中,动画都是事后才想到的,但 Flutter 团队在开发这个令人惊叹的框架时在牢记动画方面做得非常出色。 我们实际上只是触及了 Flutter 在动画方面的能力的皮毛。