如何在Flutter中开始间隔动画

时间:2019-08-28 00:40:25

标签: flutter-animation

我想为三个落在屏幕上的球设置动画。但是我希望第一个球的动画比第二个球的动画更早开始,第二个球的动画比第三个球的动画更早开始。

我试图在动画的前进之间给出某种超时,但是由于某些原因没有解决。在下面的代码中,我为三个球完成了相同的动画。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  AnimationController animationController1,
      animationController2,
      animationController3;

  Animation<double> animation, animation2, animation3;

  @override
  void initState() {
    animationController1 =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this);
    animationController2 =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this);
    animationController3 =
        AnimationController(duration: Duration(milliseconds: 300), vsync: this);

    animation = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController1, curve: Interval(0.0, 1.0)),
    );

    animation2 = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController2, curve: Interval(1.0, 2.0)),
    );

    animation3 = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController3, curve: Interval(2.0, 3.0)),
    );

    animationController1.addListener(() {
      print('1 ${animation.value}');
      print('2 ${animation.value}');
      print('3 ${animation.value}');
      setState(() {});
    });

    animationController1.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController1.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController1.forward();
      }
    });
    animationController2.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController2.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController2.forward();
      }
    });
    animationController3.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController3.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController3.forward();
      }
    });

    animationController1.forward();
    animationController2.forward();
    animationController3.forward();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                buildBallOne(),
                SizedBox(
                  width: 6.0,
                ),
                buildBallTwo(),
                SizedBox(
                  width: 6.0,
                ),
                buildBallThree()
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget buildBallOne() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController1.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }

  Widget buildBallTwo() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController2.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }

  Widget buildBallThree() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController3.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:1)

那是因为您同时运行所有控制器。

enter image description here

我只添加了一些延迟并进行了一些调整。

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {
  AnimationController animationController1, animationController2, animationController3;

  Animation<double> animation1, animation2, animation3;

  @override
  void initState() {
    animationController1 = AnimationController(
      duration: Duration(milliseconds: 600),
      vsync: this,
    );
    animationController2 = AnimationController(
      duration: Duration(milliseconds: 600),
      vsync: this,
    );
    animationController3 = AnimationController(
      duration: Duration(milliseconds: 600),
      vsync: this,
    );

    animation1 = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController1, curve: Interval(0.0, 1.0)),
    );

    animation2 = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController2, curve: Interval(0.0, 1.0)),
    );

    animation3 = Tween(
      begin: 0.0,
      end: 1.0,
    ).animate(
      CurvedAnimation(parent: animationController3, curve: Interval(0.0, 1.0)),
    );

    animationController1.addListener(() {
      print('1 ${animation1?.value}');
      print('2 ${animation2?.value}');
      print('3 ${animation3?.value}');
      setState(() {});
    });

    animationController1.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController1.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController1.forward();
      }
    });
    animationController2.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController2.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController2.forward();
      }
    });
    animationController3.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        animationController3.reverse();
      } else if (status == AnimationStatus.dismissed) {
        animationController3.forward();
      }
    });

    Future.delayed(
      Duration(milliseconds: 300),
      () => animationController1.forward(),
    );

    Future.delayed(
      Duration(milliseconds: 600),
      () => animationController2.forward(),
    );
    Future.delayed(
      Duration(milliseconds: 900),
      () => animationController3.forward(),
    );

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Container(
          child: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                buildBallOne(),
                SizedBox(
                  width: 6.0,
                ),
                buildBallTwo(),
                SizedBox(
                  width: 6.0,
                ),
                buildBallThree()
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget buildBallOne() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController1.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }

  Widget buildBallTwo() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController2.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }

  Widget buildBallThree() {
    return Container(
      margin: EdgeInsets.only(top: 100 - (animationController3.value * 50)),
      width: 35,
      height: 35,
      decoration: ShapeDecoration(
        shape: CircleBorder(),
        color: Colors.blue,
      ),
    );
  }
}

实际上,因为所有球的动画路径都相同,所以可以使用一个控制器为每个球计算不同的位置

P.s。使用Animated Widget或AnimatedBuilder,不触发setState刷新页面,将提供更好的性能。