Code前端首页关于Code前端联系我们

一个小型的 Flutter 开发示例将帮助您理解动画,动画

terry 2年前 (2023-09-23) 阅读数 75 #移动小程序

APP里充满了不同的动画,有的用GIF,有的Flare,有的Lottie...

对于Flutter原生的动画来说,也是非常强大的。

这里有一个小例子:Flutter 开发小例子带你认识动画 Animation

底部的箭头“会向上移动并逐渐变得透明,然后重复该动作”。稍后我们会讲如何实现。首先,我们来谈谈Flutter中动画的基础知识。

动画的类型

首先,Flutter中的动画分为两类:

  1. 附加动画(Tween)
  2. 我们常用的是基于物理的动画,其中我们常用的是动画。含义引自《Flutter中文网》解释:

    “Between”的缩写。在完成的动画中,定义了起始点和结束点、时间线以及定义过渡时间和速度的曲线。然后框架计算如何从起点到达终点。

    其实动画是由一系列图像组成的,补间动画根据时间计算出如何走,然后向我们展示这一系列图像。

    动画

    Flutter中的动画系统是基于“Animation”的。 “Widgets”可以直接将这些动画合并到它们自己的构建方法中,以读取它们的当前值或跟踪它们的状态变化,或者它们可以用作传递给其他小部件的更复杂动画的基础。

    Animation是一个抽象类,它的主要功能是存储动画的状态和值。

    一般使用.addListener方法添加监听器。您可以在此侦听器中获取当前状态和值,但只要发生操作,此侦听器就会回调。如果您只想监听当前状态,那么只需使用

    .addStatusListener 方法即可。

    “动画”有以下几种状态:

    1. 关闭:一般情况下动画都是从这个状态开始的
    2. forward:运行时可以是这样
    3. backward: :运行时也可以是这样 Completed:完成后就变成了这个

    AnimationController

    要创建动画,首先要创建一个AnimationController。除了Animation本身之外,AnimationController也可用于控制动画。例如,让动画向前播放和停止。

    既然需要先创建AnimationController,我们先看看它的构造函数来了解如何创建它:

    AnimationController({
      double value,
      this.duration,
      this.reverseDuration,
      this.debugLabel,
      this.lowerBound = 0.0,
      this.upperBound = 1.0,
      this.animationBehavior = AnimationBehavior.normal,
      @required TickerProvider vsync,
    }) : assert(lowerBound != null),
    assert(upperBound != null),
    assert(upperBound >= lowerBound),
    assert(vsync != null),
    _direction = _AnimationDirection.forward {
      _ticker = vsync.createTicker(_tick);
      _internalSetValue(value ?? lowerBound);
    }
    复制代码

    参数说明: eueu ​​duration:duration

  3. re诗句持续时间:反向持续时间动画
  4. debugLabel:用于调试的字符串
  5. lowerBound:下限,动画可以获取且已取消的最小值不能为空。
  6. upperBound:上限,动画可以获得的最大值,动画结束时的值。它不能为空。
  7. animationBehavior:配置禁用动画时的[AnimationController]行为。
  8. vsync:当前上下文的 TickerProvider,可以使用 resync 进行更改。它不能为空。需要

垂直同步。在带动画的类后面加上和TickerProviderStateMixin就可以了。

Tween

由于AnimationController的默认值为0 - 1,如果要设置0 - 1以外的值,则必须使用Tween开始值和结束值。 Tween是最常用的,但也有很多具体的Tween类型:

  • ColorTween
  • SizeTween
  • TweenCurveTween...只是定义了如何在两个值之间进行插值。如果您想要当前的具体值,您仍然需要动画。这里有两种方法可以获取当前状态的具体参考:
    1. evaluate:这种方法适合已经写好的动画,并且在该动画在小部件运行时重建小部件时更有效。
    2. animate:此方法返回一个适合使用此小部件为小部件创建新动画的动画。

    要实现一开始的效果

    先想一下这个效果:“向上滚动,逐渐变成透明,然后重复这个动作。”

    1. 向上滚动:我们利用容器的边框属性
    2. 逐渐透明:应用Opacity图层,利用opacity属性来实现
    3. 重复动作:找出动画当前的状态,然后重新开始

    明白需求后,我们先写控件。

    由于我们的动画效果有点复杂,所以我们使用AnimatedWidget来封装组​​件,避免大量重复setState。

    所以,Widget的动画代码如下:

    class AnimatedUpArrow extends AnimatedWidget {
      final Tween<double> _opacityTween = Tween(begin: 1, end: 0);
      final Tween<double> _marginTween = Tween(begin: 0, end: 50);
    
      AnimatedUpArrow({Key key, Animation<double> animation})
          : super(key: key, listenable: animation);
    
    
      @override
      Widget build(BuildContext context) {
        final Animation<double> animation = listenable;
        return SafeArea(
          child: Center(
            child: Opacity(
              opacity: _opacityTween.evaluate(animation),
              child: Container(
                margin: EdgeInsets.only(bottom: _marginTween.evaluate(animation)),
                child: Image.asset("images/UP.png", width: 20, height: 24,),
              ),
            ),
          ),
        );
      }
    }
    复制代码

    首先创建两个补间。由于两个动画是同时执行的,因此最好使用Tween求值方法通过动画来计算插值。

    代码很简单,然后看看如何使用这个小部件:

    AnimationController _animationController;
    Animation<double> _animation;
    
    @override
    void initState() {
      super.initState();
      _animationController = AnimationController(
        vsync: this, duration: Duration(milliseconds: 1400));
      _animation =
        CurvedAnimation(parent: _animationController, curve: Curves.linear);
    
      _animationController.addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          Future.delayed(Duration(milliseconds: 500), () {
            _animationController.reset();
          });
        } else if (status == AnimationStatus.dismissed) {
          _animationController.forward();
        }
      });
      
      _animationController.forward();
    }
    
    @override
    Widget build(BuildContext context) {
      return AnimatedUpArrow(
        animation: _animation,
      );
    }
    复制代码

    简单解释:

    首先定义AnimationControllerAnimationController为持续时间0,0,0然后定义 动画,立即将控制器设置为控制器,将曲线设置为线性,

    ,然后定义动画完成的❝StatusListener。如果完成,500毫秒后执行。延迟后,动画重置并继续动画,创建重复动画效果。

    最后,在build方法中传入集合Animation,这样就可以使用刚才定义的AnimatedWidget来根据插值来计算这个动画了

    现在顶部动画就准备好了。

    总结

    Flutter 中很多原生 Widget 都使用了 AnimatedWidget,例如AnimatedPositioned❙。看它的构建方法:

    @override
    Widget build(BuildContext context) {
      return Positioned(
        child: widget.child,
        left: _left?.evaluate(animation),
        top: _top?.evaluate(animation),
        right: _right?.evaluate(animation),
        bottom: _bottom?.evaluate(animation),
        width: _width?.evaluate(animation),
        height: _height?.evaluate(animation),
      );
    复制代码

    OK 可以看到和我们上面使用的方法是一样的,就是评估方法。

    作者:颤笔记
    链接:https://juejin.im/post/5d646c9e6fb9a06b084d037e
    来源:掘金商业转载请联系作者授权。非商业转载请注明出处。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门