欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Flutter 具有方向性动画和内置显式动画

最编程 2024-04-17 14:30:29
...

你好!在之前的文章中,我们学习了如何使用Flutter的隐式动画制作一些很棒的动画。AnimatedFoo和TweenAnimationBuilder使您能够将一些基本动画放到应用程序中。这些动画通常朝一个方向进行,从开始到结束,在那里停止。在幕后,Flutter正在掌控局面,假设你的意图,并处理你担心从一件事到另一件事的任何需要。

对于许多动画目标来说,这是完美的,但有时,时间之箭会让我们感觉时间被锁定。所以,当我们停下来思考热力学定律和宇宙不可避免的热死亡时,如果我们能把时间倒转,然后再做一遍,那岂不是很好? 

进入我们的第一次进入Flutter显式动画!我们今天不会构建任何时间机器,但是我们将学习如何使用过渡小部件来获得对动画的更多控制。 

Transition小部件是一组Flutter小部件,它们的名称都以Transition结尾。ScaleTransition、DecoratedBoxTransition、SizeTransition等。它们看起来和感觉都很像我们的动画小部件。例如,PositionedTransition为小部件在不同位置之间的转换设置动画。这很像AnimatedPositioned,但有一个主要区别:这些转换小部件是AnimatedWidget的扩展。这使它们成为显式动画。

但是,对于我们这些应用程序开发者来说,这到底意味着什么呢?让我们一步一步来了解是什么让这些动画起作用。

 在这里,我们将创建一个银河系比例的动画,使用这个起始图像。但是,在最初的无生命状态下,它感觉不太像银河系。我们的第一个任务是:混入旋转动画。

RotationTransition 为例

RotationTransition小部件是一个方便的小部件,它负责处理所有的三角函数和数学变换,使事物旋转。它的构造函数只需要三件事:

RotationTransition({
  Widget child,
  Alignment alignment,
  Animation<double> turns,
})

首先是一个孩子-我们要旋转的小部件。星系很适合,所以我们把它放在那里:

RotationTransition(
  child: GalaxyFitz(),
  alignment: null, /*TODO*/
  turns: null, /*TODO*/
)

下一步,我们需要给我们的星系旋转的点旋转过渡。我们银河系的黑洞大致在我们通常预期的图像*。所以,我们将给出一个中心对齐,使我们所有的旋转数学“对齐”到那个点。

RotationTransition(
  child: GalaxyFitz(),
  alignment: Alignment.center,
  turns: null, /*TODO*/
)

最后,这个神秘的名字是什么?API文档告诉我们这是…一个动画?!?我们不是在创作动画吗? 

 RotationTransition文档告诉我们,turns属于动画类型。

 别担心!这是使RotationTransition和所有其他转换小部件成为显式动画的一部分。我们可以用一个动画容器和一个变换来完成同样的旋转效果,但是我们会旋转一次然后停止。有了我们的显式动画,我们可以控制时间,使我们的星系永远不会停止旋转。

turns属性需要一个值,并在该值更改时通知它。动画就是这样。对于RotationTransition,该值对应于我们旋转了多少次,或者更具体地说,一次旋转完成的百分比。

创建AnimationController

 对于动画控制器来说,创建Animation是最简单的方法之一。这个控制器处理监听嘀嗒¹,并为我们提供一些有用的控制动画正在做什么。

 我们需要在一个有状态的小部件中创建它,因为在不远的将来保持控制器上的句柄是很重要的。我们也要在初始化状态下处理它,因为我们也要处理它的初始化状态。

 我们必须给AnimationController的构造函数提供两个参数。第一个是持续时间,即我们的动画持续时间。我们在这里的全部原因是我们需要一个物体来告诉我们,在一个旋转中我们有多远。默认情况下,AnimationController“发射”值从0.0到1.0。这些值的数量和粒度取决于我们希望一次旋转需要多长时间。幸运的是,Dart给了我们一个Duration类来使用。为了这个演示,我们应该让星系在每次旋转5秒到2.3亿年之间旋转。那么每转15秒怎么样?

_animationController = AnimationController(
  duration: Duration(seconds: 15),
  // TODO: finish constructing me.
);

下一个必需的参数是vsync。如果你将来来这里,欢迎回来!我们希望你已经了解了vsync的一切。对于那些从过去来到这里的人,我们只想说,这就是让Flutter引用对象来通知更改的原因。就是这样,它需要混合一些ticker provider 代码。

以后的一篇文章将深入探讨vsync和ticker提供商的更多细节。 如果我们把事情放在那里,什么事也不会发生。那是因为我们得到了一个控制器,但没有按下任何按钮!我们希望我们的星系永远旋转,对吧?为此,我们将要求控制器不断重复动画。

_animationController = AnimationController(
  duration: Duration(seconds: 15),
  vsync: this,)
..repeat();

最后,通过将动画控制器传递给RotationTransition中的turns参数,我们可以返回并替换我们留下的空白。

RotationTransition(
  child: GalaxyFitz(),
  alignment: Alignment.center,
  turns: _animationController,
)

而且,尽管我们现在有一个无限旋转的星系,但这仍然感觉不到我们能控制时间。银河系现在就这么做了,对吧?不过,别忘了,我们有一个控制器的手柄。让我们好好利用它

使用AnimationController 

允许任何人控制银河系似乎有点过于宽容,所以我要把它变成一个复活节彩蛋。我将向银河系添加一个同级项,这是一个简单的按钮,隐藏在角落中,我将传递给控制器的引用,以便在它的onTap侦听器中,我们可以停止或重新启动动画。 控制器维护——除其他外——动画的状态,如果我们正在运行,我们可以检查并停止;如果没有,我们可以重新启动。然后,就这样!通过使用动画控制器,我们可以按需控制动画。但这不是你用控制器能做的全部。 有了它,您还可以将动画设置为特定值(或向后),以给定的速度向前推动动画,或使用同一控制器控制多个动画。

这只是我们在Flutter中第一次尝试显式动画。我们看到了转换小部件如何与AnimationController一起工作,以提供一些方向性和对动画工作方式的控制。在以后的文章中,我们将深入研究显式动画,以及如何获得更多的定制。