Implicit Flutter Animations

Oct 4 2022 · Dart 2.17, Flutter 3.0, Visual Studio Code 1.7

Part 1: Animation Fundamentals

02. Understand Implicit Animations

Episode complete

Play next episode

Next
About this episode
Leave a rating/review
See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 01. Learn Animation Basics Next episode: 03. Add Realistic Motions with Curves

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Notes: 02. Understand Implicit Animations

The student materials have been reviewed and are updated as of August 2022.

The updated material uses null safety and also deploys the use of const keyword with constant constructors as per the Flutter lint rules that is used to encourage good coding practises.

Transcript: 02. Understand Implicit Animations

What just happened in the previous episode? Why did the AnimatedContainer know how to animate the widget?

Well, the AnimatedContainer belongs to a group of widgets called “ImplicitlyAnimatedWidget.” Implicit Animated widgets provides a way to add animations without adding additional complexities. You provide a target value and once that target value changes, the underlying widget animates.

Implicit Animated widgets are easily indentified with the “AnimatedFoo” naming pattern where “Foo” is replaced with a specified feature or widget in our case the Container widget. They are simply animatable versions of commonly used widgets. So, an

  • AnimatedOpacity: animates the opacity of its child
  • AnimatedDefaultTextStyle: animates the style of a Text
  • AnimatedPadding: animates the padding

Flutter provides different ImplicitlyAnimatedWidgets and we would be covering some of them in this course.

Now, these widgets produce implicit animations. Implicit animations occurs between changes in a target value. In our example, the animation occurs between 100 and 200 for both the width and height properties since they both depend on the size variable.

This means that, they know how to animate the underlying widget based on changes in their properties. The process of generating values between the old and the new value is called “Interpolation.”

The ImplicitlyAnimatedWidgets handles the interpolation for the animation. And remember from the previous episode, the in between values would be generated about 60 times per second. These change in values would be responsible for drawing the widget with the updated values on new frames which in turn creates the animation.

ImplicitlyAnimatedWidgets also control and manage their animations so you cant explicitly manage the underlying animation controller and do stuffs like pausing or reversing the animation. All these happens behind the scene.

ImplicitlyAnimatedWidgets provide you with 3 properties to control your animations:

  • the duration which specifies how long the animation should last
  • the curve which controls the rate of change of the animation within the given duration. This, as you would see soon helps gives our animations realistic motions.
  • and finally, the onEnd callback function which is called whenever an animation completes. This can be used to trigger another animation or perform some othe action like navigating to a different route.

These might seem limiting but as you’ll find out over this course, there are lots of applications for implicit animations.

The AnimatedContainer is one of the most powerful implicit animated widget. You’re not limited to just animating its width and height. You can animate its:

  • color
  • alignment
  • margin
  • transform
  • borderRadius
  • padding
  • decoration

and other properties available to this widget. These are otherwise known as animation triggers.

Let’s animate the color of the Container. Go ahead and update your code to the following:

...
// class member
Color boxColor = Colors.green;
...
// build
AnimatedContainer(
...
    color: boxColor,
...
//FAB
onPressed: () {
    setState(() {
        ...
        boxColor = boxColor == Colors.green ? Colors.orange : Colors.green;
    });
},

We added the boxColor variable and set it to green as its initial value. Next, we assigned it to the color property of the Container. Finally, we toggled it btw green and orange whenever we click the FAB. Okay, let’s try it out.

The color animates accordingly. Now, let’s swap the grow animation with a fade animation. To do this, we’ll be using the AnimatedOpacity widget. Update your code to the following:

...
// class member
double boxOpacity = 1.0;
...
// build (wrap the container with AnimatedOpacity)
...
AnimatedOpacity(
    opacity: boxOpacity,
    duration: const Duration(milliseconds: 1000),
    child: Container(
        // duration: Duration(milliseconds: 1000) // comment out the duration
...
//FAB
onPressed: () {
    setState(() {
        ...
        boxOpacity = boxOpacity == 1.0 ? 0.0 : 1.0;
    });
},

First, the declared the boxOpacity variable which holds a double value. This would be use to control the opacity.

Inside the AnimatedOpacity widget, the opacity property is of type double and it controls the visibility of the widget. At 0.0, the child widget is inivisible while at 1.0 it is fully visible. So at 0.5, the child would be half visible.

We toggle the boxOpacity variable inside the setState method and this triggers the fade in and fade out effect. And remember, the AnimatedOpacity handles the transition. Let’s go ahead and see how the animation looks. Nice, it fades in gradually over a duration of a second.

We can also combine different implictiy animations to run simultaneosly. Let’s grow the box as it fades in together with its color. This time around, we would be using one variable to trigger the whole animation since they all run at the same time. Let’s update our code to the following:

...
bool showBox = false;
...
AnimatedOpacity(
    opacity: showBox ? 1.0 : 0.0,
    duration: const Duration(milliseconds: 1000),
    child: AnimatedContainer(
        duration: const Duration(milliseconds: 1000),
        width: showBox ? 200 : 100,
        height: showBox ? 200 : 100,
        color: showBox ? Colors.orange : Colors.green,
    ),
)
...
setState(() {
    showBox = !showBox;
});
...

In here, we declared a new boolean variable: showBox and we set it to false. It would be the main trigger for our animation because we want all the animations to run at once. So there would be no need to have different variables to run a single animation sequence. It just my personal preference and not a rule of thumb. Next, the showBox variable is used to toggle the opacity of the widget. We also used it to toggle the width, height and color of the AnimatedContainer.

And finally, we trigger the change via the setState method. This is done by inverting the boolean variable whenever we click the FAB.(Highlight the !showBox part) Let’s try it out. We can see that the box animates with all the different animations playing accordingly.