阅读 29

Flutter AnimatedWidget,AnimatedBuilder动画(2.4)

Flutter学习之动画篇,理解有限,各位看客多多指点,多多包涵~

普通动画

在Flutter当中设置动画,需要使用动画控制器(AnimationController),使用它来控制动画的时间,开始,反向,暂停,等操作,


	 AnimationController _mAnimationController;
	 
	 _mAnimationController = new AnimationController(
	      vsync: this,
	      duration: Duration(seconds: 5),
	    );
复制代码

AnimationController 参数介绍:

  • 参数一: vsync参数,存在vsync时会防止屏幕外动画(动画的UI不在当前屏幕时)消耗不必要的资源,通常情况使用with SingleTickerProviderStateMixin即可

class _AnimationPageState extends State with SingleTickerProviderStateMixin {

}

补充:
如果项目中只有一个动画使用的是 SingleTickerProviderStateMixin,项目中有2个以上的动画则使用TickerProviderStateMixin

  • 参数二:duration参数:用来设置动画执行时间
  • _mAnimationController.forward() //开始执行动画
  • _mAnimationController.reverse() //反向执行动画
  • _mAnimationController.reset() //重置
  • _mAnimationController.dispose() //删除/停止动画
  • _mAnimationController.repeat();//重复执行

Animation实例有2中状态:

  • Animation<double>改变的是帧状态
  • Animation<Color>改变的是颜色状态

接下来介绍的是 Animation<double>,设置动画,最后会为大家带来改变Animation<Color>的例子,大家可以尝试的写一下~,

Animation<double>:Tween补间动画:

	Animation<double> _mAnimation;

	_mAnimation = new Tween<double>(begin: 0, end: 200)
        //添加动画控制器
        .animate(_mAnimationController)
        ..addListener(() {
            setState(() {
              print('_mAnimationValue:${_mAnimationValue}');
              _mAnimationValue = _mAnimation.value;
            });
          })
          ..addStatusListener((status) {
            setState(() {
              print('status:${status}');
              _mAnimationStaus = status;
            });
          });
复制代码

Tween参数:

  • begin 开始
  • end 结束

然后通过animate()将动画控制器(AnimationController)添加到Tween参数当中.这里结合起来可以理解为,5秒内从0,变化到200,_mAnimation.value就是每秒获取的状态

细心的同学可能会发现,这里的…addListener()是什么意思

..addListener(() {
            setState(() {
              print('_mAnimationValue:${_mAnimationValue}');
              _mAnimationValue = _mAnimation.value;
            });
          })
          ..addStatusListener((status) {
            setState(() {
              print('status:${status}');
              _mAnimationStaus = status;
            });
复制代码

其实啊,这是Dart中的语法,叫做联级符号,和这样写是一样的效果:

   _mAnimation = new Tween<double>(begin: 0, end: 200)
        //添加动画控制器
        .animate(_mAnimationController);

    _mAnimation.addListener(() {
            setState(() {
              print('_mAnimationValue:${_mAnimationValue}');
              _mAnimationValue = _mAnimation.value;
            });
          });
    _mAnimation.addStatusListener((status) {
            setState(() {
              print('status:${status}');
              _mAnimationStaus = status;
            });
          });
复制代码
  • addListener() 他可以为Animation添加帧监听,每一帧都会被调用,通过setState()来触发
  • addStatusListener() 他可以为Animation添加’动画状态改变’监听
addStatusListener 用來监听动画当前状态
     *  dismissed  动画在开始处停止。
     *  forward,   动画从头到尾都在运行。
     *  reverse     动画正在向后运行,从头到尾。
     *  completed   动画在结尾处停止。
复制代码

还有一种方式:

 //创建动画控制器
 AnimationController _mAnimationController;
	 
 _mAnimationController = new AnimationController(
	      vsync: this,
	      duration: Duration(seconds: 5),
	    );
  //执行动画
 _mAnimationController.forward();


 @override
  Widget build(BuildContext context) {
    return FadeTransition(
		 //设置渐变动画
        opacity: _tweenAnimation,
		child: ;
	 );
  }
复制代码

Curve:

Curve官方给的是’曲线’,但我感觉它类似于android的插值器(Interpolator)
Curve事例:Curve参考文档
_mAnimation通过chain()方法来添加Curve()

来看看完整代码吧:

建议在initState()初始化时来创建对象;


@override
  void initState() {
    //初始刷Controller设置执行时间
    _mAnimationController = new AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    );
    //设置变化区间 并监听
    _mAnimation = new Tween<double>(begin: 0, end: 200)
     	//执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
        .chain(new CurveTween(curve: Curves.bounceIn))
        //添加动画控制器
        .animate(_mAnimationController);

    _mAnimation.addListener(() {
            setState(() {
              print('_mAnimationValue:${_mAnimationValue}');
              _mAnimationValue = _mAnimation.value;
            });
          });
    _mAnimation.addStatusListener((status) {
            setState(() {
              print('status:${status}');
              _mAnimationStaus = status;
            });
          });
    /**
     * addStatusListener 用來监听动画当前状态
     *  dismissed  动画在开始处停止。
     *  forward,   动画从头到尾都在运行。
     *  reverse     动画正在向后运行,从头到尾。
     *  completed   动画在结尾处停止。
     */

    super.initState();
  }
复制代码
Container(
        alignment: Alignment.center,
        child: Column(
          children: [
            GestureDetector(
              onTap: () {
                //重置
                _mAnimationController.reset();
                //开始
                _mAnimationController.forward();
              },
              child: Text("开始",style: TextStyle(fontSize: 25),),
            ),
            Container(
              width: _mAnimationValue,
              height: _mAnimationValue,
              child: FlutterLogo(),
            )
          ],
        ),
      )
复制代码

最后需要在页面消失的时候将动画控制器也给销毁掉,这样能更好的资源回收.

  @override
  void dispose() {
    // TODO: implement dispose
    //资源回收
    _mAnimationController.dispose();
    super.dispose();
  }
复制代码

效果图(1.1):

在这里插入图片描述

AnimatedWidget

AnimatedWidget其实就是简化了addListener()方法,只需要继承自AnimatedWidget()就可以实现动画效果


  AnimationController _mAnimationController;
  Animation<double> _mAnimation;

@override
  void initState() {
    //初始刷Controller设置执行时间
    _mAnimationController = new AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    );
    //设置变化区间 并监听
    _mAnimation = new Tween<double>(begin: 0, end: 200)
        //执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
        .chain(new CurveTween(curve: Curves.bounceIn))
        //添加动画控制器
        .animate(_mAnimationController);
        //不用在写addListener()监听方法监听帧变化了!
    super.initState();
  }
复制代码

继承自AnimatedWidget,将Animation<double>参数传进来,然后给到父类的listenable,在获取到value设置给布局即可.

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

  @override
  Widget build(BuildContext context) {
    //通过父类方法listenable来获取Animation<double>对象
    Animation<double> _mAnimation = listenable;
    return Container(
      width: _mAnimation.value,
      height: _mAnimation.value,
      child: FlutterLogo(),
    );
  }
}
复制代码

资源回收:

  @override
  void dispose() {
    // TODO: implement dispose
    //资源回收
    _mAnimationController.dispose();
    super.dispose();
  }
复制代码
Container(
        alignment: Alignment.center,
        child: Column(
          children: [
            GestureDetector(
              onTap: () {
                //重置
                _mAnimationController.reset();
                //开始
                _mAnimationController.forward();
              },
              child: Text("开始",style: TextStyle(fontSize: 25),),
            ),
            //调用AnimationWidget将Animaiton传给他即可~!
            AnimationWidget(animaiton: _mAnimation),

          ],
        ),
      ),
复制代码

效果图(1.2):
在这里插入图片描述

AnimatedBuilder

AnimatedBuilder也是简化了addListener()方法,直接将布局和动画给到AnimatedBuilder,就可以实现动画效果

动画条件不变:


  AnimationController _mAnimationController;
  Animation<double> _mAnimation;

@override
  void initState() {
    //初始刷Controller设置执行时间
    _mAnimationController = new AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    );
    //设置变化区间 并监听
    _mAnimation = new Tween<double>(begin: 0, end: 200)
        //执行曲线 类似于android中的插值器Interpolator 默认Curves.linear
        .chain(new CurveTween(curve: Curves.bounceIn))
        //添加动画控制器
        .animate(_mAnimationController);
        //不用在写addListener()监听方法监听帧变化了!
    super.initState();
  }
复制代码

创建AnimatedBuilder必填参数是:
builder: (BuildContext context, Widget child) {} );
返回的是动画
animation也是必填参数

	AnimatedBuilder(
              child: Container(
                color: Colors.yellow,
                width: 100,
                height: 100,
                child: FlutterLogo(),
              ),
              builder: (BuildContext context, Widget child) {
                return Container(
                //这次不从0开始显示,从100开始显示看看效果~
                  width: _mAnimation.value + 100,
                  height: _mAnimation.value + 100,
                  //这里的child就是上边给的FlutterLogo()
                  child: child,
                );
              },
              //必填参数将动画给导布局图片
              animation: _mAnimation,
            )
复制代码

效果图(1.3):
在这里插入图片描述

Animation<Color>事例:

我是采用的AnimatedWidget办法

第一步还是不会变的,还是设置动画控制器(AnimationController),然后设置Color颜色变化状态,由Colors.amber颜色变化到 Colors.tealAccent颜色

 @override
  void initState() {
    //初始刷Controller设置执行时间
    _mAnimationController = new AnimationController(
      vsync: this,
      duration: Duration(seconds: 5),
    );
    
    //改变颜色状态
    _mAnimationColor =
        new ColorTween(begin: Colors.amber, end: Colors.tealAccent)
            .animate(_mAnimationController);

    super.initState();
  }
复制代码

我这里的Animation<double>和Animation<Color>复用的,建议大家分开写!

class AnimationWidget extends AnimatedWidget {
  
  //isColor true是Animation<Color>类型
  //        false 是Animation<double>类型
  bool isColor;

  AnimationWidget(
      {Key key,
      Animation<Color> animaitonColor,
      Animation<double> animaitonDouble,
      @required this.isColor})
      : super(key: key, listenable:isColor == true? animaitonColor :animaitonDouble);

  Animation<Color> _mAnimationColor;
  Animation<double> _mAnimationDouble;

  @override
  Widget build(BuildContext context) {
    //通过父类方法listenable来获取Animation<double>对象
    if (isColor) {
      _mAnimationColor = listenable;
    } else {
      _mAnimationDouble = listenable;
    }

    return isColor == true
        ? Container(
            width: 100,
            height: 100,
            color: _mAnimationColor.value,
            child: FlutterLogo(),
          )
        : Container(
            width: _mAnimationDouble.value,
            height: _mAnimationDouble.value,
            child: FlutterLogo(),
          );
  }
}
复制代码

资源回收

  @override
  void dispose() {
    // TODO: implement dispose
    //资源回收
    _mAnimationController.dispose();
    super.dispose();
  }
复制代码

效果图(1.4):
在这里插入图片描述

完整代码

上一章:Flutter Ink,InkWell,InkResponse水波纹实现(2.3)

下一章:Flutter Hero动画(2.5)

原创不易,您的点赞就是对我最大的支持,请留下您的点赞吧~

文章分类
Android
文章标签