https://flutter.cn/docs/development/ui/animations
动画的基本组成
Animation
作用:保存动画的差值和状态。整个动画执行过程可以是线性的、曲线的、一个步进函数或者任何其他曲线,由Curve来决定。
给Animation添加帧监听器
动画开始、结束、正向或反向时的回调
Curve
作用:定义动画曲线
内置Curves曲线:
- linear:匀速
 
- decelerate:匀减速
 
- ease:开始加速后面减速
 
- easeIn:开始慢后面快
 
- easeOut:开始快后面慢
 
- easeInOut:开始慢,然后加速,最后再减速
 
AnimationController
作用:用于控制动画,包含启动forward、停止stop、反向播放reverse等
Ticker
当创建AnimationController时,需要传递一个vsync参数,它接收一个TickerProvider类型。通常我们会将SingleTickerProviderStateMixin添加到State的定义中,然后将State对象作为vsync的值。
SingleTickerProviderStateMixin和TickerProviderStateMixin,这两个类的区别就是是否支持创建多个TickerProvider,可以使用多个AnimationController。
Tween
默认情况下,AnimationController对象值的范围是[0.0,1.0]。如果我们需要构建UI的动画值在不同的范围或不同的数据类型,则可以使用Tween来添加映射以生成不同的范围或数据类型的值。例如,像下面示例,Tween生成[-200.0,0.0]的值
1
   | final Tween doubleTween = Tween<double>(begin: -200.0, end: 0.0);
   | 
 
Tween构造函数需要begin和end两个参数。Tween的唯一职责就是定义从输入范围到输出范围的映射。输入范围通常为[0.0,1.0],但这不是必须的,我们可以自定义需要的范围。Tween继承自Animatable,而不是继承自Animation,Animatable中主要定义动画值的映射规则。
1 2 3 4 5 6 7 8 9 10 11 12
   | final Tween colorTween =     ColorTween(begin: Colors.transparent, end: Colors.black54);
  final AnimationController controller = AnimationController(   duration: const Duration(milliseconds: 500),    vsync: this, ); Animation<int> alpha = IntTween(begin: 0, end: 255).animate(controller);
  final Animation curve = CurvedAnimation(parent: controller, curve: Curves.easeOut); Animation<int> alpha = IntTween(begin: 0, end: 255).animate(curve);
 
   | 
 
Tween对象不存储任何状态,相反,它提供了evaluate(Animation animation)方法,它可以获取动画当前映射值。 Animation对象的当前值可以通过value()方法取到。evaluate函数还执行一些其他处理,例如分别确保在动画值为0.0和1.0时返回开始和结束状态
Tween的子类:
- ColorTween
 
- ConstantTween
 
- CurveTween
 
- IntTween
 
- RectTween
 
- ReverseTween
 
- SizeTween
 
- StepTween
 
基本用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
   | class ScaleAnimationRoute extends StatefulWidget {   const ScaleAnimationRoute({Key? key}) : super(key: key);      @override   _ScaleAnimationRouteState createState() => _ScaleAnimationRouteState(); }
 
  class _ScaleAnimationRouteState extends State<ScaleAnimationRoute>     with SingleTickerProviderStateMixin {   late Animation<double> animation;   late AnimationController controller;      @override   initState() {     super.initState();     controller = AnimationController(       duration: const Duration(seconds: 2),       vsync: this,     );
                animation = Tween(begin: 0.0, end: 300.0).animate(controller);     animation.addListener(() {         setState(() => {});       });
           controller.forward();   }
    @override   Widget build(BuildContext context) {     return Center(       child: Image.asset(         "imgs/avatar.png",         width: animation.value,         height: animation.value,       ),     );   }      @override   dispose() {          controller.dispose();     super.dispose();   } }
 
 
  | 
 
以上写法封装后便是AnimatedBuilder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
   |  class AnimatedBuilderExample extends StatefulWidget {    @override    _AnimatedBuilderExampleState createState() => _AnimatedBuilderExampleState();  }     class _AnimatedBuilderExampleState extends State<AnimatedBuilderExample>      with SingleTickerProviderStateMixin {    late AnimationController _controller;    late Animation<double> _animation;       @override    void initState() {      super.initState();      _controller = AnimationController(        duration: Duration(seconds: 2),        vsync: this,      );           _animation = Tween<double>(begin: 50.0, end: 200.0).animate(_controller);       _controller.forward();    }       @override    Widget build(BuildContext context) {      return Scaffold(        appBar: AppBar(          title: Text('AnimatedBuilder Demo'),        ),        body: Center(          child: AnimatedBuilder(            animation: _controller,            builder: (BuildContext context, Widget? child) {              return Container(                width: _animation.value,                height: _animation.value,                color: Colors.green,                child: Center(                  child: Text(                    'Hello',                    style: TextStyle(color: Colors.white),                  ),                ),              );            },          ),        ),      );    }       @override    void dispose() {      _controller.dispose();      super.dispose();    }  } 
 
 
  | 
 
隐式动画
Implicit Animations
ImplicitlyAnimatedWidget的子类,可以方便的设置各种各种属性的动画。隐式动画只需要传递duration,即可自行驱动。简单的动画场景可使用。
系统实现的隐式动画
- AnimatedContainer:Container属性变化过渡动画
 
- AnimatedAlign:alignment变化过渡动画
 
- AnimatedOpacity:透明度
 
- AnimatedPositioned:配合Stack使用
 
- AnimatedRotation
 
- AnimatedScale
 
- AnimatedSlide
 
- AnimatedSwitcher
 
- AnimatedSize
 
- AnimatedCrossFade
 
- AnimatedTheme
 
- AnimatedPositionedDirectional
 
- AnimatedPhysicalModel
 
- AnimatedPadding
 
常用属性
- duration:设置动画时长
 
- curve:设置动画曲线
 
- onEnd:动画结束回调
 
自定义隐式动画
使用TweenAnimationBuilder,该 Widget 使用的时候我们需要传递 duration 参数动画时间、tween 参数动画要设置的值的范围(补间)、重要的还有 builder 参数,builder函数的参数包含context、补间参数tween的类型、还有child
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   |  TweenAnimationBuilder<double>(     tween: Tween<double>(begin: 0, end: 2 * pi),     duration: Duration(seconds: 2),     builder: (BuildContext context, double angle, Widget child) {         return Transform.rotate(         angle: angle,         child: Container(             color: Colors.red,             width: 100,             height: 100,         ),         );     }, ),
 
 
 
 
  | 
 
显示动画
Explicit Animations
继承自AnimatedWidget,通过传入listenable来驱动视图变化。自己来控制动画的运行
- AlignTransition
 
- AnimatedBuilder
 
- DecoratedBoxTransition
 
- DefaultTextStyleTransition
 
- RelativePositionedTransition
 
- RotationTransition:旋转
 
- ScaleTransition:缩放动画,可以指定中心点
 
- FadeTransition:透明度动画
 
- SizeTransition:宽高变化,不会引起内容的变形
 
- SlideTransition:位移动画
 
交织动画
多个动画交错在一起,通过一个controller控制。
1 2 3 4 5
   |  AnimationController controller = AnimationController(); Tween<double>(begin: 0, end: 100).animate(CurvedAnimation(parent: controller, curve: Interval(0.0, 0.5, curve: Curves.ease))); ColorTween(begin: Colors.green, end: Colors.red,).amimate(CurvedAnimation(parent: controller, curve: Interval(0.5, 0.8, curve: Curves.ease,)));
 
 
  | 
 
自定义动画
参考