【Flutter 实战】动画核心

移动开发 作者: 2024-08-24 21:20:01
老孟导读:动画系统是任何一个UI框架的核心功能,也是开发者学习一个UI框架的重中之重,同时也是比较难掌握的一部分,下面我们就一层一层的揭开 Flutter 动画的面纱。 任何程序的动画原理都是一样的,

AnimationController

class AnimationBaseDemo extends StatefulWidget {
  @override
  _AnimationBaseDemoState createState() => _AnimationBaseDemoState();
}

class _AnimationBaseDemoState extends State<AnimationBaseDemo> {
  double _size = 100;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          setState(() {
            _size = 200;
          });
        },child: Container(
          height: _size,width: _size,color: Colors.blue,alignment: Alignment.center,child: Text('点我变大',style: TextStyle(color: Colors.white,fontSize: 18),),);
  }
}
class _AnimationBaseDemoState extends State<AnimationBaseDemo> with SingleTickerProviderStateMixin{
  double _size = 100;
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this,duration: Duration(milliseconds: 500));
  }
  ...
}
  • vsync:当创建 AnimationController 时,需要传递一个vsync参数,存在vsync时会防止屏幕外动画消耗不必要的资源,单个 AnimationController 的时候使用 SingleTickerProviderStateMixin,多个 AnimationController 使用 TickerProviderStateMixin
  • duration:表示动画执行的时间。
class _AnimationBaseDemoState extends State<AnimationBaseDemo> with SingleTickerProviderStateMixin{
  double _size = 100;
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this,duration: Duration(milliseconds: 500));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },);
  }
  
  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
_controller = AnimationController(vsync: this,duration: Duration(milliseconds: 500))
..addListener(() {
  setState(() {
    _size = 100+100*_controller.value;
  });
});
_controller = AnimationController(vsync: this,duration: Duration(milliseconds: 500),lowerBound: 100,upperBound: 200)
..addListener(() {
  setState(() {
    _size = _controller.value;
  });
})
_controller = AnimationController(
    vsync: this,upperBound: 200)
  ..addStatusListener((status) {
    print('status:$status');
  })
  • dismissed:动画停止在开始处。
  • forward:动画正在从开始处运行到结束处(正向运行)。
  • reverse:动画正在从结束处运行到开始处(反向运行)。
  • completed:动画停止在结束处。
  • forward:正向执行动画。
  • reverse:反向执行动画。
  • repeat:反复执行动画。
  • reset:重置动画。
_controller = AnimationController(
    vsync: this,upperBound: 200)
  ..addStatusListener((AnimationStatus status) {
    if(status == AnimationStatus.completed){
      _controller.reverse();
    }else if(status == AnimationStatus.dismissed){
      _controller.forward();
    }
  })
  ..addListener(() {
    setState(() {
      _size = _controller.value;
    });
  });
_controller =
    AnimationController(vsync: this,duration: Duration(milliseconds: 500))
      ..addListener(() {
        setState(() {
          _color = Color.lerp(_startColor,_endColor,_controller.value);
        });
      });
class TweenDemo extends StatefulWidget {
  @override
  _TweenDemoState createState() => _TweenDemoState();
}

class _TweenDemoState extends State<TweenDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
	Color _startColor = Colors.blue;
  Color _endColor = Colors.red;

  Color _color = Colors.blue;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this,duration: Duration(milliseconds: 500))
          ..addListener(() {
            setState(() {
              _color = Color.lerp(_startColor,_controller.value);
            });
          });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },child: Container(
          height: 100,width: 100,color: _color,child: Text(
            '点我变色',);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
class _TweenDemoState extends State<TweenDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation<Color> _animation;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this,duration: Duration(milliseconds: 500))
          ..addListener(() {
            setState(() {});
          });
    _animation =
        ColorTween(begin: Colors.blue,end: Colors.red).animate(_controller);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },color: _animation.value,);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}

Curve

class CurveDemo extends StatefulWidget {
  @override
  _CurveDemoState createState() => _CurveDemoState();
}

class _CurveDemoState extends State<CurveDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  Animation _animation;

  @override
  void initState() {
    super.initState();
    _controller =
        AnimationController(vsync: this,duration: Duration(milliseconds: 1000))
          ..addListener(() {
            setState(() {});
          });

    _animation = Tween(begin: 100.0,end: 200.0)
        .chain(CurveTween(curve: Curves.bounceIn))
        .animate(_controller);
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _controller.forward();
        },child: Container(
          height: _animation.value,width: _animation.value,child: Text(
            '点我变大',);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }
}
_controller =
    AnimationController(vsync: this,duration: Duration(milliseconds: 1000),lowerBound: 100.0,upperBound: 200.0)
      ..addListener(() {
        setState(() {});
      });
_animation = CurveTween(curve: Curves.bounceIn).animate(_controller);
_controller =
        AnimationController(vsync: this,end: 200.0)
        .chain(CurveTween(curve: Curves.bounceIn))
        .animate(_controller);

那就自定义一个动画曲线

class _StairsCurve extends Curve {

  @override
  double transformInternal(double t) {
    return t;
  }
}
class _StairsCurve extends Curve {
  //阶梯的数量
  final int num;
  double _perStairY;
  double _perStairX;

  _StairsCurve(this.num) {
    _perStairY = 1.0 / (num - 1);
    _perStairX = 1.0 / num;
  }

  @override
  double transformInternal(double t) {
    return _perStairY * (t / _perStairX).floor();
  }
}
_animation = Tween(begin: 100.0,end: 200.0)
    .chain(CurveTween(curve: _StairsCurve(5)))
    .animate(_controller);

总结

AnimationController _controller;
Animation _animation;

@override
void initState() {
  super.initState();
  _controller =
      AnimationController(vsync: this,duration: Duration(milliseconds: 1000))
        ..addListener(() {
          setState(() {});
        });

  _animation = Tween(begin: 100.0,end: 200.0)
      .animate(_controller);
}
_animation = _controller.drive(Tween(begin: 100.0,end: 200.0));
_animation = Tween(begin: 100.0,end: 200.0)
    .chain(CurveTween(curve: Curves.linear))
    .animate(_controller);
_animation = _controller
    .drive(CurveTween(curve: Curves.linear))
    .drive(Tween(begin: 100.0,end: 200.0));
_animation = CurveTween(curve: Curves.linear)
    .animate(_controller);
_animation = _controller.drive(CurveTween(curve: Curves.linear));
class MultiControllerDemo extends StatefulWidget {
  @override
  _MultiControllerDemoState createState() => _MultiControllerDemoState();
}

class _MultiControllerDemoState extends State<MultiControllerDemo>
    with TickerProviderStateMixin {
  AnimationController _sizeController;
  AnimationController _colorController;
  Animation<double> _sizeAnimation;
  Animation<Color> _colorAnimation;

  @override
  void initState() {
    super.initState();
    _sizeController =
        AnimationController(vsync: this,duration: Duration(milliseconds: 2000))
          ..addListener(() {
            setState(() {});
          });

    _sizeAnimation = _sizeController
        .drive(CurveTween(curve: Curves.linear))
        .drive(Tween(begin: 100.0,end: 200.0));

    _colorController =
        AnimationController(vsync: this,duration: Duration(milliseconds: 1000))
          ..addListener(() {
            setState(() {});
          });

    _colorAnimation = _colorController
        .drive(CurveTween(curve: Curves.bounceIn))
        .drive(ColorTween(begin: Colors.blue,end: Colors.red));
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: GestureDetector(
        onTap: () {
          _sizeController.forward();
          _colorController.forward();
        },child: Container(
          height: _sizeAnimation.value,width: _sizeAnimation.value,color: _colorAnimation.value,child: Text(
            '点我变化',);
  }

  @override
  void dispose() {
    super.dispose();
    _sizeController.dispose();
    _colorController.dispose();
  }
}
  • AnimationController:动画控制器,控制动画的播放、停止等。继承自Animation< double >,是一个特殊的Animation对象,默认情况下它会线性的生成一个0.0到1.0的值,类型只能是 double 类型,不设置动画曲线的情况下,可以设置输出的最小值和最大值。
  • Curve:动画曲线,作用和Android中的Interpolator(差值器)类似,负责控制动画变化的速率,通俗地讲就是使动画的效果能够以匀速、加速、减速、抛物线等各种速率变化。
  • Tween:将 AnimationController 生成的 [0,1]值映射成其他属性的值,比如颜色、样式等。
  1. 创建 AnimationController
  2. 如果需要 Tween 或者 Curve,将 AnimationController 与其关联,Tween 和 Curve 并不是必须的,当然大部分情况都需要。
  3. 将动画值作用于组件,当没有Tween 和 Curve 时,动画值来源于AnimationController,如果有 Tween 和 Curve,动画值来源于 Tween 或者Curve 的 Animation。
原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_68030.html