Step One: Tweening

In this nugget, you're going to build a simple animation that looks like this:

custom animation gif

This is actually 8 animation intervals in one animation, but divided over only4 widgets.

What'll you learn ?

  • AnimatedWidget
  • Tweens
  • AnimationController
  • Transform

This 'app' will have 4 classes:

  • BarLoadingScreen extends StatefulWidget

  • _BarLoadingScreenState extends State<BarLoadingScreen> with TickerProviderStateMixin

  • This is basically the highest widget in the tree

  • It will eventually hold the AnimationController

  • Its Basically the entire brains of the animation

  • Bar extends StatelessWidget

  • Just the dumb widget for display

  • PivotAnimation extends AnimatedWidget

  • This is the Wrapper for the bar

  • It turn the Tweens and Animations into Transforms

Step 1: Build Boiler Plate

The following will just render the four bars to the screen. After this you canfocus on implementing the actual animations.

  1. void main() {
  2. runApp(new MaterialApp(
  3. home: Scaffold(
  4. body: new BarLoadingScreen(),
  5. ),
  6. ));
  7. }
  8. class BarLoadingScreen extends StatefulWidget {
  9. @override
  10. _BarLoadingScreenState createState() => new _BarLoadingScreenState();
  11. }
  12. class _BarLoadingScreenState extends State<BarLoadingScreen> {
  13. @override
  14. Widget build(BuildContext context) {
  15. return new Container(
  16. child: new Center(
  17. child: new Row(
  18. mainAxisAlignment: MainAxisAlignment.center,
  19. children: <Widget>[
  20. new Bar(),
  21. new Bar(),
  22. new Bar(),
  23. new Bar(),
  24. ],
  25. ),
  26. ),
  27. );
  28. }
  29. }
  30. class Bar extends StatelessWidget {
  31. @override
  32. Widget build(BuildContext context) {
  33. return new Container(
  34. width: 35.0,
  35. height: 15.0,
  36. decoration: new BoxDecoration(
  37. color: const Color.fromRGBO(0, 0, 255, 1.0),
  38. borderRadius: new BorderRadius.circular(10.0),
  39. boxShadow: [
  40. new BoxShadow(
  41. color: Colors.black12,
  42. blurRadius: 8.0,
  43. spreadRadius: 1.0,
  44. offset: new Offset(1.0, 0.0),
  45. ),
  46. new BoxShadow(
  47. color: Colors.black26,
  48. blurRadius: 6.0,
  49. spreadRadius: 1.5,
  50. offset: new Offset(1.0, 0.0),
  51. ),
  52. ]),
  53. );
  54. }
  55. }

Step 2: Add Controller and Tween

All Flutter Animations need two things:

  • An AnimationController. This controller has two important purposes. First,it defines how long the animaiton will last via it's duration property. It'sother purpose is to provide a handful of methods that tell the animation how tobehave. i.e. repeat(), forward() and reverse().

  • Tweens. Tween is short for 'in between', and it represents the value ofthe property changing in between frames. For example, if you're animating theopacity of a container from 0.0 to 1.0, your tween will represent the values at0.1, 0.2, and so on.

You set up Tweens by creating new Tween class and passing the starting andending values. In the opacity example, because opacity values are doublesyou'd do something like this:

  1. Tween<double> tween = new Tween<double>(begin: 0.0, end: 1.0);
  2. // then you'd animate it, but more on that in a bit

But if you wanted to animate from blue to green, Flutter Tweens can do that too:

  1. ColorTween colorTween = new ColorTween(
  2. begin: Colors.blue[400],
  3. end: Colors.green[400],
  4. );
  5. // then you'd animate it, but more on that in bit.

The point is, Tween's return values at periods between start and finish, whichyou can pass as props to whatever you're animating, so it's always gettingupdated.

2.5 Detour: Color Tween Example

Go ahead and add this to your boiler plate. It's a small detour to see the mostbasic animation in Flutter.

  1. // You have to add this class mixin in order for flutter to know to treat it as
  2. // an animation containing widget
  3. class _BarLoadingScreenState extends State<BarLoadingScreen>
  4. with SingleTickerProviderStateMixin {
  5. AnimationController _controller; // new
  6. Animation<Color> animation; // new
  7. @override
  8. initState() {
  9. super.initState();
  10. // Because this class has now mixed in a TickerProvider
  11. // It can be its own vsync. This is what you need almost always
  12. _controller = new AnimationController(
  13. duration: const Duration(milliseconds: 3000),
  14. vsync: this,
  15. );
  16. // A tween that begins at grey and ends at a green
  17. // The chained 'animate' function is required
  18. animation = new ColorTween(
  19. begin: const Color.fromRGBO(10, 10, 10, 0.5),
  20. end: const Color.fromRGBO(0, 200, 100, 0.5),
  21. ).animate(_controller)
  22. // This is a another chained method for Animations.
  23. // It will call the callback passed to it everytime the
  24. // value of the tween changes. Call setState within it
  25. // to repaint the widget with the new value
  26. ..addListener(() {
  27. setState((){});
  28. });
  29. // Tell the animation to start
  30. _controller.forward();
  31. }
  32. // This is important for perf. When the widget is gone, remove the controller.
  33. @override
  34. dispose() {
  35. _controller?.dispose();
  36. super.dispose();
  37. }
  38. @override
  39. Widget build(BuildContext context) {
  40. return new Container(
  41. // This is where you pass the animation value
  42. // Each time set state gets called,
  43. // this widget gets rebuilt,
  44. // and the value of the animation is something inbetween
  45. // the starting grey and the ending green
  46. // thanks to our ColorTween
  47. decoration: new BoxDecoration(color: animation.value),
  48. child: new Center(
  49. child: new Row(
  50. mainAxisAlignment: MainAxisAlignment.center,
  51. children: <Widget>[
  52. new Bar(),
  53. new Bar(),
  54. new Bar(),
  55. new Bar(),
  56. ],
  57. ),
  58. ),
  59. );
  60. }
  61. }

Do a full refresh on your app. Look at the background change color.