Flutter 创建符合预期的 Animation

animation.png

Flutter 当中动画有隐式动画与显式动画。实现显示动画最终目的就是获取到预期的 Animation 实例。达到这个目的需要一些类或者方法来帮助实现。

AnimationController 主要是用来控制动画,播放、暂停、监听状态等。同时继承于 Animation,其本质也是一个 Animation 实例。意味着如果没有特殊其他的效果需求那么创建完 AnimationController 就已经达到目的了。

 _controller = AnimationController(
      vsync: this,
      duration: Duration(milliseconds: 250),
 );

如果还需要给动画添加例如曲线、获取目标区间值等效果,就需要使用 Tween 或 CurveTween、CurvedAnimation 等给动画加些佐料。动画实现写法比较多,可以通过以下几种方式。

  1. drive 方法是 Animation 实例方法(例如 AnimationController 类)来组合一个 Tween 或是 CurveTween,来扩展动画效果。传入的参数类型就是其返回值类型,例如传入的是 AlignmentTween 那么其返回值类型就是 Animation

    // 将控制器与 easeIn 曲线效果以及目标对齐区间值进行相结合
    Animation _alignment3 = _controller
      .drive(CurveTween(curve: Curves.easeIn))
      .drive(AlignmentTween(
        begin: Alignment.topLeft,
        end: Alignment.topRight,
      ));
    

    注意: 该方法只允许 Animation 来调用,其他类型的调用会被断言 Failed assertion: line 169 pos 12: 'this is Animation': is not true.

  2. chain 方法功能也是组合,但与 drive 方法不同,它是 Animatable 实例(例如 SizeTween)方法用来组合 CurveTween。 其返回值类型是并非 Animation 类型而是 Animatable 类型。这就意味着在使用 chain 方法对目标 Tween 进行组合后,再通过某一些其他方法(例如 drive()、animate() )将其转换为 Animation 类型以便使用。

    // 对齐区间值与曲线 easeIn 结合
    final Animatable tween = AlignmentTween(begin: Alignment.topLeft, end: Alignment.topRight)
     .chain(CurveTween(curve: Curves.easeIn));
    // 通过 drive 将控制器与佐料结合获得 Animation 类。
    final Animation alignment2 = _controller.drive(tween);
    
    // 该实现在 Tween 拼接完后用 animate 转换,由于加了 ReverseAnimation 效果与上面方向相反
    final Animation alignment3 = AlignmentTween(
     begin: Alignment.topLeft,
     end: Alignment.topRight,
    ).chain(CurveTween(curve: Curves.easeIn)).animate(ReverseAnimation(_controller!));
    

最后使用 AnimatedBuilder 并通过读取预期 animation 实例的值来实现动画效果。

@override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _controller!,
      child: Container(
        width: 10,
        height: 10,
        color: Colors.green,
      ),
      builder: (context, child) {
        return Container(
          alignment: _animation!.value, // 读取动画从  Alignment.topLeft ->  Alignment.topRight 区间值
          width: 50,
          height: 50,
          color: Colors.red,
          child: child!,
        );
      },
    );
  }

你可能感兴趣的:(Flutter 创建符合预期的 Animation)