在之前的学习中,学会了如何给一个 Widget 设置一个简单的动画,但如果动画效果很复杂呢?

例如一个 Widget 在变换大小的同时改变颜色或者改变形状?

我们只需要把复杂动画分解成若干个简单动画,然后分别实现,最后组合在一起执行即可。

看例子:

void main() {
  runApp(MaterialApp(home: GroupAnimation()));
}

class GroupAnimation extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return GroupAnimationState();
  }
}

class GroupAnimationState extends State<GroupAnimation>
    with TickerProviderStateMixin {
  AnimationController controller;
  Animation<Color> colorAnimation;
  Animation<double> sizeAnimation;

  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(vsync: this, duration: Duration(seconds: 3));
    CurvedAnimation curvedAnimation =
        CurvedAnimation(parent: controller, curve: Curves.easeIn);

    colorAnimation = ColorTween(begin: Colors.red, end: Colors.lightGreen)
        .animate(curvedAnimation);
    sizeAnimation =
        Tween<double>(begin: 100, end: 400).animate(curvedAnimation);

    controller.addListener(() {
      if(controller.isCompleted){
        controller.repeat(reverse: true);
      }
    });
    controller.forward();

  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("组合动画"),
      ),
      body: GroupAnimationWidget(
        animation: colorAnimation,
        colorAnimation: colorAnimation,
        sizeAnimation: sizeAnimation,
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    // 动画使用完成后必需要销毁
    controller.dispose();
  }
}

class GroupAnimationWidget extends AnimatedWidget {
  GroupAnimationWidget(
      {Key key,
      Animation<Color> animation,
      Animation<Color> colorAnimation,
      Animation<double> sizeAnimation})
      : super(key: key, listenable: animation) {
    this.colorAnimation = colorAnimation;
    this.sizeAnimation = sizeAnimation;
  }

  Animation<Color> colorAnimation;
  Animation<double> sizeAnimation;

  @override
  Widget build(BuildContext context) {
    Animation<Color> animation = listenable;
    return Container(
      color: colorAnimation.value,
      width: sizeAnimation.value,
      height: sizeAnimation.value,
    );
  }
}

效果如下:

代码很简单,就不解释了。

再设想一下,我们想要动画先变色,再变形,这该怎么办呢?

还记得之前的 Curve 的子类不,用在这里不是正合适么,废话不多说,看代码:

void main() {
  runApp(MaterialApp(home: GroupAnimation()));
}

class GroupAnimation extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return GroupAnimationState();
  }
}

class GroupAnimationState extends State<GroupAnimation>
    with TickerProviderStateMixin {
  AnimationController controller;
  Animation<Color> colorAnimation;
  Animation<double> sizeAnimation;

  @override
  void initState() {
    super.initState();
    //定义共耗时 4 秒
    controller =
        AnimationController(vsync: this, duration: Duration(seconds: 4));
    //0.0~0.8 执行该 Tween,也就是前 3.2 秒是变色
    colorAnimation = ColorTween(begin: Colors.red, end: Colors.lightGreen)
        .animate(CurvedAnimation(
        parent: controller,
        curve: Interval(0.0, 0.8, curve: Curves.easeIn)));
    //0.8~1.0 执行该 Tween,也就是后 0.8 秒是变形
    sizeAnimation =
        Tween<double>(begin: 100, end: 400).animate(CurvedAnimation(
            parent: controller,
            curve: Interval(0.8, 1.0, curve: Curves.easeIn)));

    controller.addListener(() {
      if(controller.isCompleted){
        controller.repeat(reverse: true);
      }
    });
    controller.forward();

  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("组合动画"),
      ),
      body: GroupAnimationWidget(
        animation: colorAnimation,
        colorAnimation: colorAnimation,
        sizeAnimation: sizeAnimation,
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    // 动画使用完成后必需要销毁
    controller.dispose();
  }
}

class GroupAnimationWidget extends AnimatedWidget {
  GroupAnimationWidget(
      {Key key,
        Animation<Color> animation,
        Animation<Color> colorAnimation,
        Animation<double> sizeAnimation})
      : super(key: key, listenable: animation) {
    this.colorAnimation = colorAnimation;
    this.sizeAnimation = sizeAnimation;
  }

  Animation<Color> colorAnimation;
  Animation<double> sizeAnimation;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: colorAnimation.value,
      width: sizeAnimation.value,
      height: sizeAnimation.value,
    );
  }
}

效果如下:

注释也写的很清楚了,就不赘述了。

官方给了两个复杂一些的例子,但套路是一样的,可以看一下:

basic_staggered_animation

staggered_pic_selection

results matching ""

    No results matching ""