SDK 飞镖 react ive Programming Animation Mobile Cross-Platform 这篇文章是 Google flutter From scratch系列的一部分。 Google Flutter From Scratch:网格、列表和数据源 Google Flutter From Scratch:使用 firebase 服务
如果使用得当,动画可以极大地改变用户对您的应用的看法。一个拥有大量快速、微妙动画的应用程序往往比没有的应用程序看起来更加精致和专业。在人满为患的市场 Google Play 上,这可能意味着成功与失败之间的差异。
Flutter 可能是当今唯一可用的混合应用程序开发框架,它允许您创建可以以每秒 60 帧的速度持续运行的复杂动画。在本教程中,我将帮助您了解动画 Flutter 小部件的基础知识。我还将向您介绍一些可以简化动画代码的新小部件。
1.为动画准备一个小部件
Flutter 框架希望您遵循功能性、反应式的编程方法。因此,为了能够为小部件设置动画,您必须能够以适当的时间间隔重复更新其状态。
要创建一个易于动画化的小部件,首先要创建一个扩展 StatefulWidget
该类并覆盖其createState()
方法的类。在方法内部,确保返回一个State
实例。
class MyApp extends StatefulWidget { @override State<StatefulWidget> createState() { return new MyState(); } }
为了具有动画效果,与有状态小部件关联的状态对象不仅必须扩展State
类,还必须使用名为 SingleTickerProviderStateMixin
. 顾名思义,mixin 提供了一个 Ticker
对象,该对象反复生成回调,通常称为滴答声。由于刻度是在均匀的时间间隔内重复生成的,因此您可以使用它们来决定何时渲染动画的各个帧。
class MyState extends State<MyApp> with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { // More code here } }
2.创建补间动画
补间动画是您可以使用 Flutter 创建的最简单的动画之一。创建它时,您需要做的就是提供两个不同的值:一个起始值和一个结束值。然后,框架将自动生成一组中间值(或中间值),它们从起始值开始并平滑增长以匹配结束值。通过逐渐将这些中间值应用于小部件的属性,您可以为该属性设置动画。
现在让我们创建一个简单的补间动画,将小部件从屏幕的左上角移动到屏幕的右上角。换句话说,让我们 left
为小部件的属性设置动画。
要创建和控制动画,您将需要一个Animation
对象和一个 AnimationController
对象。将它们添加为您的状态的成员变量:
Animation<double> animation; AnimationController controller;
您必须通过覆盖initState()
类的方法来初始化这两个对象。在方法内部,调用AnimationController
类的构造函数来初始化控制器。它期望一个TickerProvider
对象作为其输入之一。因为 state 已经使用了SingleTickerProviderStateMixin
mixin,所以你可以传递this
给它。此外,您可以使用该duration
属性来指定动画的持续时间。
以下代码创建一个持续时间为 4 秒的动画控制器:
@override void initState() { super.initState(); controller = new AnimationController(vsync: this, duration: new Duration(seconds: 4)); // More code here }
此时,您可以创建一个Tween
对象来指定动画的开始值和结束值。
Tween tween = new Tween<double>(begin: 10.0, end: 180.0);
要将Tween
对象与AnimationController
对象关联,您必须调用其 animate()
方法。该方法的返回值是一个Animation
对象,您可以将其存储在类的第二个成员变量中。
animation = tween.animate(controller);
该Animation
对象为代码的每个刻度生成一个动画事件,您必须处理该事件才能使动画正常工作。为此,您可以使用它的addListener()
方法。此外,在事件处理程序中,您必须调用该setState()
方法来更新小部件的状态并重绘它。以下代码向您展示了如何:
animation.addListener(() { setState(() { }); });
请注意,setState()
除非您有其他状态变量要更新,否则您不必在方法内编写任何代码。
最后,要启动动画,您必须调用forward()
动画控制器的方法。
controller.forward();
动画准备好了。但是,您还没有将它应用到正在屏幕上绘制的任何小部件。现在,我建议你将它应用到一个positioned
包含 Material小部件的Icon
小部件上。为此,在创建小部件时,只需将其 left
属性的值设置为对象的value
属性Animation
。
因此,将以下覆盖该build()
方法的代码添加到状态:
@override Widget build(BuildContext context) { return new Container( color: Colors.white, child: new Stack( children: <Widget>[ new Positioned( child: new Material( child: new Icon(Icons.airport_shuttle, textDirection: TextDirection.ltr, size: 81.0 ) ), left: animation.value, // Animated value top: 30.0 // Fixed value ) ], textDirection: TextDirection.ltr,) ); }
请注意,Stack
上面的小部件树中有一个小部件,因为Positioned
小部件必须始终嵌入其中。
您现在可以运行您的应用程序来查看动画。
3.处理动画状态事件
如果您想在动画结束时收到通知,您可以将一个 AnimationStatusListener
对象附加到您的Animation
对象上。在监听器内部,如果当前动画状态为completed
或dismissed
,则可以确定动画已经结束。
Flutter 中的补间动画是可逆的。这就是为什么有两个不同的状态常量表示动画结束的原因。如果当前状态为completed
,则表示动画已在补间的结束值处结束。如果是dismissed
,则表示动画已在起始值处结束。使用这两个状态和forward()
andreverse()
方法,您可以轻松地在动画之间来回创建。
您可以将以下代码添加到initState()
方法中,向您展示如何反转和重复您在上一步中创建的动画:
animation.addStatusListener((status) { if(status == AnimationStatus.completed) controller.reverse(); else if(status == AnimationStatus.dismissed) controller.forward(); });
如果您再次运行该应用程序,您应该会看到动画无休止地重复。
4.使用动画小部件
Flutter 框架提供了一些易于制作动画的小部件,您可以使用这些小部件来使您的动画代码稍微不那么冗长且更可重用。它们都是类的子 AnimatedWidget
类,并且在它们的构造函数中是期望Animation
或AnimationController
对象。
最常用的动画小部件之一是RotationTransition
小部件。它允许您快速将旋转动画应用于其子项。要使用它,首先创建一个新的动画控制器。以下代码创建一个持续时间设置为六秒的代码:
controller = new AnimationController(vsync: this, duration: new Duration(seconds: 6));
这次要启动动画,而不是forward()
方法,使用 repeat()
方法。这确保了动画无休止地重复。
controller.repeat();
为简单起见,您可以使用Text
小部件作为小部件的子级 RotationTransition
。因此,相应地创建一个小部件树。但是,在创建 RotationTransition
小部件时,请确保将其 turns
属性的值设置为AnimationController
刚刚创建的对象。或者,您可以将两个小部件都放在一个Center
小部件中。就是这样:
@override Widget build(BuildContext context) { return new Center( child: new RotationTransition( turns: controller, child: new Text("\u{1F43A}", textDirection: TextDirection.ltr, style: new TextStyle(fontSize: 85.0),) ) ); }
在上面的代码中,我使用了 Unicode 表情符号代码点作为 Text
小部件的内容。这是允许的,因为 Flutter 开箱即用地支持表情符号。
再次运行应用程序时,您应该会在屏幕上看到如下内容:
与小部件非常相似的RotationTransition
是ScaleTransition
小部件。正如您可能已经猜到的那样,它允许您为其子级的比例设置动画。在创建它时,您需要做的就是将AnimationController
对象传递给它的scale
属性。以下代码向您展示了如何:
@override Widget build(BuildContext context) { return new Center( child: new ScaleTransition( scale: controller, child: new Text("\u{1F43A}", textDirection: TextDirection.ltr, style: new TextStyle(fontSize: 85.0),) ) ); }
您现在可以Text
在动画期间看到小部件的比例变化。
如果您想知道为什么我们没有Tween
为上述动画创建任何对象,那是因为默认情况下,AnimationController
该类使用 0.0 和 1.0 作为begin
和end
值。
5.使用曲线
我们在前面的步骤中创建的所有动画都遵循线性曲线。结果,它们看起来不太现实。通过改变Tween
对象生成中间值的方式,你可以改变它。
Flutter 有一个名为 的类CurvedAnimation
,它允许您将非线性曲线应用于补间。当您将它与Curves
提供各种曲线(例如easeIn
和)的类一起使用时easeOut
,您可以创建感觉更自然的动画。
要创建CurvedAnimation
对象,您需要一个AnimationController
对象作为父对象。您可以自由使用您在前面步骤中创建的控制器之一或创建一个新的。以下代码创建一个持续时间设置为 5 秒的新控制器,以及一个 属性设置为 曲线的CurvedAnimation
对象:curve
bounceOut
controller = new AnimationController( vsync: this, duration: new Duration(seconds: 5) ); CurvedAnimation curvedAnimation = new CurvedAnimation( parent: controller, curve: Curves.bounceOut );
您现在可以创建一个Tween
对象并CurvedAnimation
通过调用其animate()
方法将对象应用到它。一旦动画准备好了,别忘了给动画添加一个监听器,更新状态,然后调用forward()
方法启动它。
Tween myTween = new Tween<double>(begin: 150.0, end: 450.0); animation = myTween.animate(curvedAnimation); animation.addListener(() { setState(() { }); }); controller.forward();
要查看动画,让我们将其应用于Positioned
小部件的top
属性。您可以在其中随意添加任何子小部件。在下面的代码中,我添加了一个Text
显示另一个表情符号的小部件。
@override Widget build(BuildContext context) { return new Stack( children: [ new Positioned( child: new Text("\u{26BE}", textDirection: TextDirection.ltr, style: new TextStyle( fontSize: 70.0 ) ), left: 50.0, top: animation.value // Animated property ) ], textDirection: TextDirection.ltr, ); }
在热休息艺术之后,您的应用现在应该显示以下动画:
结论
您现在了解了使用 Flutter 框架创建补间动画的基础知识。在本教程中,您还学习了如何使用曲线使它们看起来更自然。请理解,在慢速模式下,这是开发过程中的默认模式,动画可能看起来有点滞后和不稳定。只有在发布模式下才能看到他们的真实表现。