Flutter 动画入门

作者: 超神的菠萝 | 来源:发表于2019-01-24 16:11 被阅读6次

    官方动画介绍

    Widget动起来

    1.使用Animation

    原理类似于Android的属性动画,和Widget分离,在一定时间内生成一系列的值,值可以是int,double,color或者string等等,每隔N毫秒,或者N秒钟获取到最新的值去替换掉Widget上的值,同时刷新布局,如果刷新间隔足够小就能起到动画的作用,例如构造一个Widget,他的width,height由动画来控制,一定时间动态更新值使Widget产生动效:

    new Container(
            margin: new EdgeInsets.symmetric(vertical: 10.0),
            height: animation.value,     
            width: animation.value,
            child: new FlutterLogo(),
          ),
    

    接下来看下如何使用Animation构建一个动态更新Widget的简单场景

    • 导入Animation
      import 'package:flutter/animation.dart';
    • 创建StatefulWidget,创建Animation的实现类AnimationController,来构造一个最简单的属性动画,并且应用到Widget上。
    class TestPage extends StatefulWidget {
      @override
      _TestPageState createState() => _TestPageState();
    }
    
    class _TestPageState extends State<TestPage>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: Duration(milliseconds: 1000));
        animationController.addListener(() {
          setState(() {});
        });
        animationController.forward(); //启动动画
      }
    
      @override
      Widget build(BuildContext context) {
        print('tag' + animationController.value.toString());
        return Center(
          child: Container(
            width: animationController.value,
            height: animationController.value * 100,
            color: Colors.red,
          ),
        );
      }
    }
    

    可以看到回调打印的是从0-1的值,要返回其他类型的数值就需要用到TweenTween有许多子类例如:

    image.png 来帮助我们实现更多的效果,使用Tween来实现从0-100的数值变换
    class _TestPageState extends State<TestPage>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
      Animation animation;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: Duration(milliseconds: 1000));
        animation = Tween(begin: 0.0,end: 100.0).animate(animationController);
        animationController.addListener(() {
          setState(() {});
        });
        animationController.forward(); //启动动画
    
      }
    
      @override
      Widget build(BuildContext context) {
        print('tag' + animationController.value.toString());
        return Center(
          child: Container(
            width: animation.value.toDouble(),
            height: animation.value.toDouble() ,
            color: Colors.red,
          ),
        );
      }
    }
    
    2.使用AnimatedWidget来简化代码AnimatedWidget,省去了addListener()以及setState()交给AnimatedWidget处理,感觉也没省掉很多。。
    class TestContainer extends AnimatedWidget {
      TestContainer({Key key,Animation animation})
          : super(key: key, listenable: animation);
     @override
      Widget build(BuildContext context) {
        // TODO: implement build
       Animation animation = listenable;
        return    Center(
          child: Container(
            width: animation.value.toDouble(),
            height: animation.value.toDouble() ,
            color: Colors.red,
          ),
        );
      }
    }
    
    class TestPage extends StatefulWidget {
      @override
      _TestPageState createState() => _TestPageState();
    }
    
    class _TestPageState extends State<TestPage>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
      Animation animation;
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: Duration(milliseconds: 1000));
        animation = Tween(begin: 0.0,end: 100.0).animate(animationController);
        animationController.forward(); //启动动画
      }
    
      @override
      Widget build(BuildContext context) {
        return TestContainer(animation: animation,);
      }
    }
    
    3.使用AnimatedWidget相关Api来再次简化代码,例如使用RotationTransitionWidget在3秒钟内旋转360度
    
    class TestPage extends StatefulWidget {
      @override
      _TestPageState createState() => _TestPageState();
    }
    
    class _TestPageState extends State<TestPage>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
      Animation animation;
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        animationController = AnimationController(
            vsync: this, duration: Duration(seconds: 10));
        animation = Tween(begin: 0.0, end: 1).animate(animationController);
        animationController.forward(); //启动动画
      }
    
      @override
      Widget build(BuildContext context) {
        return RotationTransition(turns: animation,
          child: Center(
              child: Container(color: Colors.red, width: 100, height: 100,)),);
      }
    }
    
    4.对动画过程进行监听
    animation.addStatusListener((status) {
          if (status == AnimationStatus.completed) {
            controller.reverse();
          } else if (status == AnimationStatus.dismissed) {
            controller.forward();
          }
        });
    
    5.使用AnimationBuilder,将控件和动画的控制过程进行封装
    class TestTransition extends StatelessWidget {
      TestTransition({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),
        );
      }
    }
    
    class TestPage extends StatefulWidget {
      @override
      _TestPageState createState() => _TestPageState();
    }
    
    class _TestPageState extends State<TestPage>
        with SingleTickerProviderStateMixin {
      AnimationController animationController;
      Animation animation;
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
        animationController =
            AnimationController(vsync: this, duration: Duration(seconds: 10));
        animation = Tween(begin: 0.0, end: 100.0).animate(animationController);
        animationController.forward(); //启动动画
      }
    
      @override
      Widget build(BuildContext context) {
        return TestTransition(
          child: Center(
              child: Container(
            color: Colors.red,
          )),
          animation: animation,
        );
      }
    }
    

    相关文章

      网友评论

        本文标题:Flutter 动画入门

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