在这篇文章中,我们将重点介绍向您的应用程序添加动画的最直接方法。您无需成为动画或动画术语方面的专家即可将动画添加到您的应用程序。在此过程中,我们将介绍一些小部件和术语,它们将帮助您立即开始使用动画,并为您提供本系列其余帖子的一些背景知识。
隐式动画小部件
Flutter 包括一系列小部件,它们是您可能已经在应用程序中使用过的现有小部件的动画版本,例如 Container 小部件的 AnimatedContainer 版本和 Positioned 小部件的 AnimatedPositioned 版本。
这些小部件会自动对其属性的更改进行动画处理。当您使用新的属性值重建小部件时,例如使用 StatefulWidget 的 setState,小部件会处理将动画从先前的值动画化到新的值。
上图是一个屏幕录像,其中修改了应用程序的代码,并且应用程序以动画形式显示了星形小部件的大小。
这些小部件称为隐式动画小部件。当您需要向您的应用程序添加动画时,它们通常是首选。它们提供了一种在不增加额外复杂性的情况下添加动画的方法。
AnimatedContainer 小部件
让我们仔细看看如何使用这个隐式动画小部件之一向您的应用程序添加一些动画。
在如下这个应用程序中,有一个容器和一个按钮。按下按钮时,将调用 setState,并使用新的宽度值重建容器。请注意,容器会立即更改其宽度,没有任何动画。
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
width: _bigger ? 100 : 500,
child: Image.asset('assets/star.png'),
),
RaisedButton(
onPressed: () => setState(() {
_bigger = !_bigger;
}),
child: Icon(Icons.star),
),
],
);
}
我们可以通过将 Container 小部件切换为 AnimatedContainer 小部件并指定动画持续时间来向该应用程序添加一些动画。
AnimatedContainer(
width: _bigger ? 100 : 500,
child: Image.asset('assets/star.png'),
duration: Duration(seconds: 1),
),
现在,当按下按钮时,容器逐渐从以前的宽度值动画到新值。
通过旧值和新值之间的值进行动画处理的过程称为插值。 AnimatedContainer 处理在旧值和新值更改时对其属性进行插值。
这适用于 AnimatedContainer 的所有属性,例如decoration。我们可以修改decoration中的渐变,AnimatedContainer 处理新旧渐变之间的插值:
AnimatedContainer(
decoration: BoxDecoration(
gradient: RadialGradient(
colors: [Colors.purple, Colors.transparent],
stops: [ _bigger ? 0.2 : 0.5, 1.0])
),
),
使用duration和curves控制动画
像 AnimatedContainer 这样的隐式动画小部件有两个属性,您可以使用它们来控制动画的行为。您可以通过设置duration属性来控制过渡到新值所需的时间。
AnimatedContainer(
width: _bigger ? 100 : 500,
child: Image.asset('assets/star.png'),
duration: Duration(seconds: 5),
),
您还可以使用Curve控制小部件从旧值插值到新值的方式。Curves控制随时间的变化率,可以帮助您的动画感觉更逼真。在这个例子中,我们将Curve从默认的linear curve更改为quintic curve:
AnimatedContainer(
width: _bigger ? 100 : 500,
child: Image.asset('assets/star.png'),
duration: Duration(seconds: 1),
curve: Curves.easeInOutQuint,
),
上图左边是 linear右边是quintic
有许多不同的内置Curves可用于为您的动画增添一些个性,您还可以定义自己的自定义曲线。曲线甚至可以是不连续的,如SawTooth curve。
下面是一个名为 SineCurve 的自定义曲线的示例,它使用正弦函数来制作一条反弹的曲线:
class SineCurve extends Curve {
final double count;
SineCurve({this.count = 1});
@override
double transformInternal(double t) {
return sin(count * 2 * pi * t) * 0.5 + 0.5;
}
}
在这里,SineCurve 使星星上下弹跳:
概括总结
Flutter 提供隐式动画小部件,它们是普通小部件的动画版本。您可以使用durations和curves来控制这些小部件的动画方式。
AnimatedContainer 是一个非常强大的隐式动画小部件,因为它有许多影响其外观的属性,并且所有这些属性都是自动插值的。
所有其他隐式动画小部件也是功能强大且易于使用的选项,用于添加动画而不增加很多复杂性。
此外,您不一定需要将这些小部件放入 StatefulWidget 中并使用 setState,您可以像这个例子中那样使用 StreamBuilder 和 FutureBuilder 来触发动画。
//AnimatedContainer with FutureBuilder
FutureBuilder(
future: future,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
double width;
switch(snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.active:
width = 0;
break;
case ConnectionState.done:
width = 500;
break;
}
return AnimatedContainer(
width: width,
child: Image.asset('assets/star.png'),
duration: Duration(seconds: 1),
);
}
),