JoJo的个人博客

记录精彩的程序人生

目录
Flutter动画
/  

Flutter动画

Flutter中对动画进行了抽象,主要涉及AnimationCurveControllerTween这四个角色,它们一起配合来完成一个完整动画

Animation

主要的功能是保存动画的插值和状态

  1. addListener

    它可以用于给Animation添加帧监听器,在每一帧都会被调用。帧监听器中最常见的行为是改变状态后调用setState()来触发UI重建

    通过animation.value来获取当前值

  2. addStatusListener

    它可以给Animation添加“动画状态改变”监听器;动画开始、结束、正向或反向(见AnimationStatus定义)时会调用状态改变的监听器

    AnimationStatus枚举类中定义

    枚举值 含义
    dismissed 动画在起始点停止
    forward 动画正在正向执行
    reverse 动画正在反向执行
    completed 动画在终点停止

Curve

指定动画过程,默认是匀速的

下面没有全部列举出来,具体可以查看文档Curves

Curves曲线 动画过程
linear 匀速的
decelerate 匀减速
ease 开始加速,后面减速
easeIn 开始慢,后面快
easeOut 开始快,后面慢
easeInOut 开始慢,然后加速,最后再减速

AnimationController

AnimationController用于控制动画,它包含动画的启动forward()、停止stop() 、反向播放 reverse()、重置reset等方法

代码示例

class _AnimationPageState extends State<AnimationPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;
  AnimationStatus animationStatus;
  double animationValue;

  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(duration: Duration(seconds: 2), vsync: this);
    animation = CurvedAnimation(parent: controller, curve: Curves.bounceIn);
    animation = Tween<double>(begin: 0, end: 300).animate(controller)
      ..addListener(() {
        setState(() {
          animationValue = animation.value;
        });
      })
      ..addStatusListener((AnimationStatus status) {
        setState(() {
          animationStatus = status;
        });
      });
    controller.forward();
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
  
  void start() {
    controller.reset();
    controller.forward();
  }
  
  ...
}

使用AnimationWidget简化动画实现

通过集成AnimatedWidget来简化动画的实现,内部简化了addListener()setState()的逻辑,允许我们将动画widget分离出来。

代码示例

class AnimationWidgetPage extends StatefulWidget {
  @override
  _AnimationWidgetPageState createState() => _AnimationWidgetPageState();
}

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

  @override
  Widget build(BuildContext context) {
    final Animation<double> animation = listenable;
    return Center(
      child: Container(
        margin: EdgeInsets.symmetric(vertical: 10),
        height: animation.value,
        width: animation.value,
        child: FlutterLogo(),
      ),
    );
  }
}

class _AnimationWidgetPageState extends State<AnimationWidgetPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;


  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(duration: Duration(seconds: 2), vsync: this);
    animation = Tween<double>(begin: 0, end: 300).animate(controller);
    controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimationWidget实现动画'),
      ),
      body: Center(
        child: AnimatedLogo(animation: animation,),
      ),
    );
  }
}

使用AnimatedBuilder重构动画

通过AnimatedBuilder可以将渲染逻辑分离出来,实现动画的复用

class AnimationWidgetPage extends StatefulWidget {
  @override
  _AnimationWidgetPageState createState() => _AnimationWidgetPageState();
}

class _AnimationWidgetPageState extends State<AnimationWidgetPage>
    with SingleTickerProviderStateMixin {
  Animation<double> animation;
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(duration: Duration(seconds: 2), vsync: this);
    animation = Tween<double>(begin: 0, end: 300).animate(controller);
    controller.forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimationBuilder重构动画'),
      ),
      body: Center(
        child: AnimatedBuilder(
          animation: animation,
          child: FlutterLogo(),
          builder: (BuildContext ctx, Widget child) {
            return Center(
              child: Container(
                margin: EdgeInsets.symmetric(vertical: 10),
                height: animation.value,
                width: animation.value,
                child: child,
              ),
            );
          },
        ),
      ),
    );
  }
}

参考文档

Flutter中文网-动画结构


标题:Flutter动画
作者:SunnySky
地址:https://www.tianyang.pub/articles/2020/07/02/1593664027155.html

评论