美文网首页Flutter
Flutter(三十六)Animation动画

Flutter(三十六)Animation动画

作者: 天色将变 | 来源:发表于2019-07-20 15:47 被阅读0次
一.图片放大示例

要点:

  • AnimationController,用于设定动画的执行时间,以及动画的开启、反转等动作。
    controller = new AnimationController(duration: const Duration(seconds: 4), vsync: this);
  • Animation,用于设定动画取值范围,并可增加动画监听,addListener是帧监听,每一帧都会回调。
    animation = new Tween(begin: 100.0, end: 300.0).animate(controller)
    ..addListener(() {
    // 通过setState实现重绘
    setState(() => {});
    });
  • controller.forward() // 启动动画
  • controller.dispose() // 释放动画资源
image.png
class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 4), vsync: this);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 300.0).animate(controller)
      ..addListener(() {
        // 通过setState实现重绘
        setState(() => {});
      });
    //启动动画
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: Image.asset("images/avatar.jpg",
          width: animation.value, height: animation.value),
    );
  }

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}

二.取值变化曲线

变化的取值,从begin到end,默认是线性变化的。变化过程可以设定曲线函数,如:

  • animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);

Curves 变化曲线,有很多种:

  • linear 线性
  • bounceIn 弹性
  • ease 开始快后来慢
  • easeIn 开始慢后来快
  • 。。。。。。
class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
    // 值变化曲线
    animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 400.0).animate(animation)
      ..addListener(() {
        // 通过setState实现重绘
        setState(() => {});
      });
    //启动动画
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return new Center(
      child: Image.asset("images/avatar.jpg",
          width: animation.value, height: animation.value),
    );
  }

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}
三.AnimatedWidget

上面使用addListener和setState实现重绘,AnimatedWidget则简化了这个操作。继承AnimatedWidget后,可以直接使用animation的值。

class AnimatedImage extends AnimatedWidget {
  AnimatedImage({Key key, Animation<double> animation})
      : super(key: key, listenable: animation);

  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return new Center(
      child: Image.asset("images/avatar.jpg",
          width: animation.value,
          height: animation.value
      ),
    );
  }
}


class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
    // 值变化曲线
    animation=CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
    //启动动画
    controller.forward();
  }

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

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}
四. AnimatedBuilder

构造方法:

const AnimatedBuilder({
    Key key,
    @required Listenable animation,
    @required this.builder,
    this.child,
  }) 
  • animation 定义的动画
  • child 作用的目标,也就是要给哪个widget添加动画
  • build 封装了绘制过程
class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
    // 值变化曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
    //启动动画
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: animation,
      child: Image.asset("images/avatar.jpg"),
      builder: (BuildContext context, Widget child) {
        return new Center(
          child: Container(
            height: animation.value,
            width: animation.value,
            child: child,
          ),
        );
      },
    );
  }

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}
五.封装动画

将动画与目标分离开,制定动画过程,传入目标child widget。

class GrowTransition extends StatelessWidget {
  GrowTransition({this.child, this.animation});// 传入目标和动画设定

  final Widget child;
  final Animation<double> animation;

// 对目标child设置动画执行过程
  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
      ),
    );
  }
}


class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
    // 值变化曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
    //启动动画
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return GrowTransition(
      animation: animation,
      child: Image.asset("images/avatar.jpg"),
    );
  }

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}
六.状态监听器
  • addListener 是每一帧的监听回调
  • addStatusListener 监听的是动画过程的状态,包括:
    • dismissed 动画停止
    • forward 动画开始正向执行
    • reverse 动画开始反向执行
    • completed 动画执行完毕
class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;
  Animation<double> animation;

  initState() {
    super.initState();
    // 设定动画执行时间
    controller = new AnimationController(
        duration: const Duration(seconds: 3), vsync: this);
    // 值变化曲线
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    //图片宽高从100变到300
    animation = new Tween(begin: 100.0, end: 400.0).animate(animation);
    // 添加状态监听
    animation.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        //动画执行结束时反向执行动画
        controller.reverse();
      } else if (status == AnimationStatus.dismissed) {
        //动画恢复到初始状态时执行动画(正向)
        controller.forward();
      }
    });
    //启动动画
    controller.forward();
  }

  @override
  Widget build(BuildContext context) {
    return GrowTransition(
      animation: animation,
      child: Image.asset("images/avatar.jpg"),
    );
  }

  dispose() {
    //释放动画资源
    controller.dispose();
    super.dispose();
  }
}
欢迎关注我的公众号:Flutter和Dart开发实践
让我们共同学习进步,It is never too late to learn!
image.png

相关文章

网友评论

    本文标题:Flutter(三十六)Animation动画

    本文链接:https://www.haomeiwen.com/subject/scculctx.html