Google从零开始振奋:动画小部件

如果正确使用动画,则可以极大地改变用户对您应用的看法。 与没有动画的应用程序相比,拥有许多快速,细腻的动画的应用程序看起来更精致,更专业。 在人满为患的市场Google Play上,这可能意味着成功与失败之间的区别。

Flutter也许是当今唯一可用的混合应用程序开发框架,它允许您创建可以每秒60帧连续运行的复杂动画。 在本教程中,我将帮助您了解Flutter小部件动画的基础知识。 我还将向您介绍一些可以简化动画代码的新小部件。

1.准备动画小部件

Flutter框架希望您遵循实用的反应式编程方法。 因此,要使小部件具有动画效果,您必须能够以适当的时间间隔重复更新其状态。

要创建易于制作动画的小部件,请先创建一个扩展StatefulWidget类的类并覆盖其createState()方法。 在方法内部,请确保您返回一个State实例。

class MyApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new MyState();
  }
}

为了具有动画效果,与有状态窗口小部件关联的状态对象不仅必须扩展State类,还必须使用一个称为SingleTickerProviderStateMixin的混合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对象作为其输入之一。 因为国家已经使用了SingleTickerProviderStateMixin混入,你可以通过this给它。 此外,您可以使用duration属性来指定动画的持续时间。

以下代码创建一个持续时间为四秒的动画控制器:

@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();

动画已准备就绪。 但是,您仍未将其应用于屏幕上绘制的任何小部件。 现在,我建议您将其应用于包含“材质Icon小部件的“ Positioned小部件。 为此,在创建窗口小部件时,只需将其left属性的value设置为Animation对象的value属性。

因此,将以下代码(覆盖了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()reverse()方法,您可以轻松地在动画之间来回创建。

您可以将以下代码添加到initState()方法中,向您展示如何反转和重复在上一步中创建的动画:

animation.addStatusListener((status) {
    if(status == AnimationStatus.completed)
        controller.reverse();
    else if(status == AnimationStatus.dismissed)
        controller.forward();
});

如果再次运行该应用程序,您将看到动画不断重复。

4.使用动画小部件

Flutter框架提供了一些易于制作动画的小部件,您可以使用这些小部件使动画代码的冗长程度略微降低,但可重用性更高。 它们都是AnimatedWidget类的子类,并且期望在其构造函数中使用AnimationAnimationController对象。

最常用的动画小部件之一是RotationTransition小部件。 它允许您快速将旋转动画应用于其子级。 要使用它,首先创建一个新的动画控制器。 以下代码创建一个持续时间设置为六秒的代码:

controller = new AnimationController(vsync: this,
                    duration: new Duration(seconds: 6));

要这次启动动画,请使用repeat()方法,而不是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开箱即用地支持表情符号。

再次运行该应用程序时,您应该在屏幕上看到以下内容:

ScaleTransition小部件与RotationTransition小部件非常相似。 您可能已经猜到了,它可以为子级的动画设置动画。 创建它时,您需要做的就是将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类一起使用时,该类提供了各种曲线,例如easeIneaseOut ,您可以创建更自然的动画。

要创建CurvedAnimation对象,您需要一个AnimationController对象作为父对象。 您可以自由使用您在前面的步骤中创建的控制器之一,也可以创建一个新的控制器。 以下代码创建一个新控制器,其持续时间设置为五秒,以及一个CurvedAnimation对象,其curve属性设置为bounceOut曲线:

controller = new AnimationController(
    vsync: this,
    duration: new Duration(seconds: 5)
);

CurvedAnimation curvedAnimation = new CurvedAnimation(
    parent: controller,
    curve: Curves.bounceOut
);

现在,您可以创建一个Tween对象,并通过调用其animate()方法将CurvedAnimation对象应用于该对象。 动画准备好后,别忘了向动画添加侦听器,更新状态,然后调用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框架创建补间动画的基础。 在本教程中,您还学习了如何使用曲线使它们看起来更自然。 一定要了解,在慢速模式(这是开发过程中的默认模式)下,动画可能看起来有些滞后且不稳定。 只有在发布模式下,您才能看到它们的真实性能。

要了解更多信息,请参阅官方文档

翻译自: https://code.tutsplus.com/tutorials/google-flutter-from-scratch-animating-widgets--cms-31709