Flutter-动画

flutter 动画前言

今天对Flutter动画进行一次突击,这篇文章是我对Flutter动画的使用和理解,有可能有不对的地方,欢迎大家给我指正

重要的类

  • Animation< double >
    在Flutter中,Animation对象本身和UI渲染没有任何关系。Animation是一个抽象类,它拥有其当前值和状态(完成或停止)。其中一个比较常用的Animation类是Animation。Flutter中的Animation对象是一个在一段时间内依次生成一个区间之间值的类。Animation对象的输出可以是线性的、曲线的、一个步进函数或者任何其他可以设计的映射。 根据Animation对象的控制方式,动画可以反向运行,甚至可以在中间切换方向。
    Animation还可以生成除double之外的其他类型值,如:Animation< Color > 或 Animation< Size >。
    Animation对象有状态。可以通过访问其value属性获取动画的当前值。
    Animation对象本身和UI渲染没有任何关系。
  • AnimationController
    AnimationController是一个特殊的Animation对象,在屏幕刷新的每一帧,就会生成一个新的值。默认情况下,AnimationController在给定的时间段内会线性的生成从0.0到1.0的数字。
final AnimationController controller = new AnimationController(
    duration: const Duration(milliseconds: 2000), vsync: this);

AnimationController派生自Animation,因此可以在需要Animation对象的任何地方使用。 但是,AnimationController具有控制动画的其他方法。例如,.forward()方法可以启动动画。数字的产生与屏幕刷新有关,因此每秒钟通常会产生60个数字,在生成每个数字后,每个Animation对象调用添加的Listener对象。
当创建一个AnimationController时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画(译者语:动画的UI不在当前屏幕时)消耗不必要的资源。 通过将SingleTickerProviderStateMixin添加到类定义中,可以将stateful对象作为vsync的值。

  • CurvedAnimation
    CurvedAnimation 将动画过程定义为一个非线性曲线.
final CurvedAnimation curve =
    new CurvedAnimation(parent: controller, curve: Curves.easeIn);
  • Tween
    默认情况下,AnimationController对象的范围从0.0到1.0。如果您需要不同的范围或不同的数据类型,则可以使用Tween来配置动画以生成不同的范围或数据类型的值。例如,以下示例,Tween生成从-200.0到0.0的值:
final Tween doubleTween = new Tween<double>(begin: -200.0, end: 0.0);

Tween对象不存储任何状态。相反,它提供了evaluate(Animation<double> animation)方法将映射函数应用于动画当前值。 Animation对象的当前值可以通过value()方法取到。evaluate函数还执行一些其它处理,例如分别确保在动画值为0.0和1.0时返回开始和结束状态。

Tween.animate

要使用Tween对象,请调用其animate()方法,传入一个控制器对象。例如,以下代码在500毫秒内生成从0到255的整数值。

final AnimationController controller = new AnimationController(
    duration: const Duration(milliseconds: 500), vsync: this);
Animation<int> alpha = new IntTween(begin: 0, end: 255).animate(controller);

注意animate()返回的是一个Animation,而不是一个Animatable。
以下示例构建了一个控制器、一条曲线和一个Tween:

  final AnimationController  controller = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
 final Animation  animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
    Animation<int> alpha = new IntTween(begin: 0, end: 255).animate(animation);
  • 动画通知
    一个Animation对象可以拥有Listeners和StatusListeners监听器,可以用addListener()addStatusListener()来添加。 只要动画的值发生变化,就会调用监听器。一个Listener最常见的行为是调用setState()来触发UI重建。动画开始、结束、向前移动或向后移动(如AnimationStatus所定义)时会调用StatusListener。 下一节中有一个addListener()方法的例子。监视动画的进度展示了如何调用addStatusListener()

如何构建一个动画

  • 通常创建一个动画需要注意的是这个里面的addListener()我们必须手动执行setState()来刷新UI界面
import 'package:flutter/material.dart';

class CurvedAnimationPage extends StatefulWidget {
  final String title;
  CurvedAnimationPage({Key key, this.title}) : super(key: key);
  @override
  _CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}

class _CurvedAnimationPageState extends State<CurvedAnimationPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
    animation = Tween(begin: 0.0, end: 300.0).animate(controller)
      ..addListener(() {
        setState(() {
          // animation.value;
        });
      })
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          controller.reverse();
        } else if (status == AnimationStatus.dismissed) {
          controller.forward();
        }
      });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('曲线动画'),
        ),
        body: Container(
          width: animation.value,
          height: animation.value,
          child: FlutterLogo(),
        ));
  }
}
  • 通过AnimatedWidget来创建动画这里不需要手动修改setState()
import 'package:flutter/material.dart';

class CurvedAnimationPage extends StatefulWidget {
  final String title;
  CurvedAnimationPage({Key key, this.title}) : super(key: key);
  @override
  _CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}

class _CurvedAnimationPageState extends State<CurvedAnimationPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
    animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          controller.reverse();
        } else if (status == AnimationStatus.dismissed) {
          controller.forward();
        }
      });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
      return AnimatedLogo(animation: animation,);
  }
}

// AnimatedWidget 的使用
class AnimatedLogo extends AnimatedWidget {
  static final _opacityTween = Tween<double>(begin: 0.1, end: 1);
  static final _sizeTween = Tween<double>(begin: 0.0, end: 300);

  AnimatedLogo({Key key, Animation<double> animation}):super(key:key,listenable:animation);

  @override
  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Scaffold(
        appBar: AppBar(
          title: Text(
            "曲线动画",
            style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
          ),
          // centerTitle: false,
        ),
        body: Center(
          child: Opacity(
            opacity: _opacityTween.evaluate(animation),
            child: Container(
              width: _sizeTween.evaluate(animation),
              height: _sizeTween.evaluate(animation),
              child: FlutterLogo(),
            ),
          ),
        ));
  }
}

  • 使用AnimatedBuilder创建动画
import 'package:flutter/material.dart';

class CurvedAnimationPage extends StatefulWidget {
  final String title;
  CurvedAnimationPage({Key key, this.title}) : super(key: key);
  @override
  _CurvedAnimationPageState createState() => _CurvedAnimationPageState();
}

class _CurvedAnimationPageState extends State<CurvedAnimationPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
    animation = CurvedAnimation(parent: controller,curve: Curves.easeInOutQuart)
      ..addStatusListener((status) {
        if (status == AnimationStatus.completed) {
          controller.reverse();
        } else if (status == AnimationStatus.dismissed) {
          controller.forward();
        }
      });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text('曲线动画d'),
        ),
        body: GrowTransition(child: LogoWidget(),animation: animation)
        );
  }
}

// AnimatedBuilder 的使用
class GrowTransition extends StatelessWidget {
  final Widget child;
  final Animation<double> animation;
  static final _opacityTween = Tween<double>(begin: 0.1, end: 1);
  static final _sizeTween = Tween<double>(begin: 0.0, end: 300);
  const GrowTransition({Key key,this.child,this.animation}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: AnimatedBuilder(
        animation: animation,
        child: child,
        builder: (BuildContext context, Widget child) {
          return Opacity(
            opacity: _opacityTween.evaluate(animation),
            child: Container(
              width: _sizeTween.evaluate(animation),
              height: _sizeTween.evaluate(animation),
              child: child,
            ),

          );
        },
      ),
    );
  }
}


class LogoWidget extends StatelessWidget {
  const LogoWidget({Key key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return Container(
      child:Container(
        child: FlutterLogo(),
      )
    );
  }
}
  • 旋转+缩放
 return RotationTransition(
  turns:Tween(begin:0.0,end:1.0)
  .animate(CurvedAnimation(
    parent: animation1,
    curve: Curves.fastOutSlowIn
  )),
  child:ScaleTransition(
    scale:Tween(begin: 0.0,end:1.0)
    .animate(CurvedAnimation(
        parent: animation1,
        curve:Curves.fastOutSlowIn
    )),
    child: child,
  )
);
  • 渐隐渐现
              return FadeTransition(
                opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
                    parent: animation1, 
                    curve: Curves.fastOutSlowIn)
                    ),
                child: child,
              );
  • 左右滑动动画
              return SlideTransition(
                position: Tween<Offset>(
                  begin: Offset(1.0, 0.0),
                  end: Offset(0.0, 0.0)
                  ).animate(CurvedAnimation(
                    parent: animation1,
                    curve: Curves.fastOutSlowIn
                  )),
                  child: child,
                );

本人已开通微信公众号,欢迎关注
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值