学习来源

一丶补间动画

1、动画通知—addListener()和addStatusListener()来添加

import 'packageflutteranimation.dart';
import 'packagefluttermaterial.dart';

class LogoApp extends StatefulWidget {
  _LogoAppState createState() = new _LogoAppState();
}

class _LogoAppState extends StateLogoApp with SingleTickerProviderStateMixin {
  Animationdouble animation;        动画
  AnimationController controller;     动画控制器

  initState() {
    super.initState();
    
      milliseconds 2000毫秒
      vsync 当创建一个AnimationController时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画(译者语:动画的UI不在当前屏幕时)
      消耗不必要的资源。 通过将SingleTickerProviderStateMixin添加到类定义中,可以将stateful对象作为vsync的值。
      这里指:vsync — _LogoAppState
      AnimationController是一个特殊的Animation对象,在屏幕刷新的每一帧,就会生成一个新的值。默认情况下,
      AnimationController在给定的时间段内会线性的生成从0.01.0的数字。
     
    controller = new AnimationController(duration const Duration(milliseconds 2000), vsync this);
    
      默认情况下,AnimationController对象的范围从0.01.0。如果您需要不同的范围或不同的数据类型,
      则可以使用Tween来配置动画以生成不同的范围或数据类型的值。
      Tween是一个无状态(stateless)对象,需要begin和end值。Tween的唯一职责就是定义从输入范围到输出范围的映射。
      输入范围通常为0.01.0,但这不是必须的。
     
    animation = new Tween(begin 0.0, end 300.0).animate(controller)addListener()函数调用了setState(),所以每次动画生成一个新的数字时,当前帧被标记为脏(dirty),这会导致widget的build()方法再次被调用。
    在build()中,改变container大小,因为它的高度和宽度现在使用的是animation.value。动画完成时释放控制器(调用dispose()方法)以防止内存泄漏。
      ..addListener(() {
        setState(() {
           此处已更改的状态是动画对象的值
           the state that has changed here is the animation object’s value
        });
      });
    //开始
    controller.forward();
  }

  Widget build(BuildContext context) {
    return new Center(
      child new Container(
        margin new EdgeInsets.symmetric(vertical 10.0),
        height animation.value,
        width animation.value,
        child new FlutterLogo(),
      ),
    );
  }

  dispose() {
    controller.dispose();
    super.dispose();
  }
}

void main() {
  runApp(new LogoApp());
}

2、用AnimatedWidget简化
有时间更新

3、用AnimatedBuilder重构

// Demonstrate a simple animation with AnimatedWidget

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';

/**
 * 之前的代码存在的一个问题: 更改动画需要更改显示logo的widget。更好的解决方案是将职责分离
 * 显示logo
 * 定义Animation对象
 * 渲染过渡效果
 */
/// 一丶  显示logo
class LogoWidget extends StatelessWidget {
  // Leave out the height and width so it fills the animating parent
  build(BuildContext context) {
    return new Container(
      margin: new EdgeInsets.symmetric(vertical: 10.0),
      child: new FlutterLogo(),
    );
  }
}


/// 三丶 渲染过度效果
class GrowTransition extends StatelessWidget {
  GrowTransition({this.child, this.animation});

  final Widget child;
  final Animation<double> animation;

  Widget build(BuildContext context) {
    return new Center(
      child: new AnimatedBuilder(
          animation: animation,
          builder: (BuildContext context, Widget child) {
            return new Container(
                height: animation.value, width: animation.value, child: child);
          },
          child: child),
    );
  }
}

/// 二丶定义Animation对象
class LogoApp extends StatefulWidget {
  _LogoAppState createState() => new _LogoAppState();
}

class _LogoAppState extends State<LogoApp> with TickerProviderStateMixin {
  Animation animation;
  AnimationController controller;

  initState() {
    super.initState();
    // 创建控制器
    controller = new AnimationController(
        duration: const Duration(milliseconds: 2000), vsync: this);
    // 创建曲线
    /**
     * parent — 控制器
     * curve — 曲线
     */
    final CurvedAnimation curve =
    new CurvedAnimation(parent: controller, curve: Curves.easeIn);
    // 创建动画
    animation = new Tween(begin: 0.0, end: 300.0).animate(curve);
    //开始
    controller.forward();
  }

  Widget build(BuildContext context) {
    // 参数一:显示logoWidget,参数二:动画
    return new GrowTransition(child: new LogoWidget(), animation: animation);
  }


  dispose() {
    controller.dispose();
    super.dispose();
  }
}

void main() {
  runApp(new LogoApp());
}

二丶Hero动画

有时间在更新

三丶交错动画

有时间在更新

喜欢记得点个赞哟,我叫王睿很高兴认识大家!

更多原理请参考谷歌官网:了解更多

Logo

更多推荐