Material Transitions in Flutter with the Animations Package

Sep 21 2021 Dart 2.13, Flutter, VS Code 1.59

Part 1: Material Transitions in Flutter with the Animations Package

1. Get Introduced to the Material Motion System

Lesson Complete

Play Next Lesson
Next
Save for later
About this episode
See forum comments
Cinema mode Mark as Complete Download course materials
Next episode: 2. Understand the Container Transform Animation

Prerequisites include a Flutter installation with VS Code or Android Studio and basic knowledge of using Flutter widgets. The Flutter UI Widgets course is a good starting point if you want to learn about Flutter widgets.

The Material Motion System is a set of transition patterns which is part of Google’s Material Design Specification. These animations help to add more flair to our apps and also guides the user flow and relationships between screens or widgets. This means that they are not just for stylistic purposes, instead each transition was created with specific use cases in mind.

The transition patterns include the:The Container Transform, The FadeThrough, The Fade Transition, and The Shared Axis Transition.

Now, the material design specification is just a set of guidelines on how to implement Material Design in your apps. Flutter follows these guidelines as implemented in the many widgets we’re already using when building Flutter apps.

On the other hand, the motion system is not included in the Flutter installation, but not to worry, the Flutter team got you covered. In Flutter, the Material Motion System is implemented and provided by the Animations package.

The Animations package provides different easy to use widgets that implements all the animations provided by this system. The first animation we would explore is the Container Transform Animation. It is a transition pattern that creates a morph effect between two containers while their contents are faded in and out accordingly. Let’s head over to VSCode to see it in action.

We would be working with a stripped down version of the app from the “Fluter UI Widgets” course. Go ahead and run the starter project for this episode in debug mode if you haven’t by pressing the F5 key. You can use any of your existing app to try it out since integrating the animations package is super easy.

Now, speaking of animations, we need to install the animations package. Head over to the pubspec.yaml file and add the following code in the dependencies section:

animations: ^2.0.0

Save the file. And it should automatically run pub get which gets the package.

For the first transition, we would be animating the FAB into the CreateArticle page. Go ahead and open up the main_page.dart file. Currently, the FAB navigates to the CreateArticle page using the Navigator.push() method.

The animations package provides us with OpenContainer widget that implements the container transform animation. To use this widget, update your code to the following:

floatingActionButton: OpenContainer(
    closedBuilder: (BuildContext context, _) {
        return FloatingActionButton(
            onPressed: null,
            child: Icon(Icons.add),
        );
    },
    openBuilder: (BuildContext context, _) {
        return CreateArticle();
    },
),

The base setup is pretty simple. We have the OpenContainer widget which expects two required arguments: the closedBuilder and the openBuilder. The closedBuilder is called to get the widget to display for the container’s closed state. In this case, we return the FAB and we can see it now because the container is in the closed state.

While the openBuilder…you guessed it right, simply returns the widget to display when the container is opened. In this case, we return the CreateArticle page.

If you noticed, we set the onPressed callback function of the FAB to null. This disables the button but since the entire OpenContainer widget is tappable by default, the action would still trigger to open the container.

We’ll talk about the parameters of the builders shorthly but before that, Let’s go ahead and try it out. It works. But to observe the animation better, lets slow down the app.

Hold down Ctrl + Shift + P on windows or Cmd + Shift + P for mac users to open up the Command Palette. Search for “toggle slow animations” and then select it. This slows down the app in debug mode so we can see how things play out. Let’s try it out once more.

Nice, the container transitions from the closed state to its open state smoothly and vice versa. Now, i know you might be wondering why that white box is around the FAB, right? Well, that’s the container that is being morphed or transitioned. That container is what animates from the closed state to the open state. The contents of the open and closed builders are just faded in and out as the container goes from its closed state to its open state.

Currently, the container tries to fit the bounds of the FAB. It does a pretty good job in getting the dimensions, but it doesnt get the color and the exact shape of the FAB.

Thankfully, the OpenContainer widget provides us with properties that helps us customize the look and feel of the container. Update your code to the following:

closedColor: Theme.of(context).accentColor,
closedShape: const CircleBorder(),

In here, we change the closedColor to the accentColor of our theme which is green in this case. And then, we make the closedShape a CircleBorder which is the same shape of a FAB. Save your work.

And you can see, the container matches the style of the FAB. One last thing i can notice is the elevation of the FAB. The FAB has a default elevation of 6. And it currently makes our animation look unrealistic simply because the drop shadow is on top of the OpenContainer widget. Instead, I would prefer the OpenContainer has the drop shadow. This approach would make the transition more realistic.

Now, the OpenContainer is a material design based widget so it shares some similar properties with other material widgets. For example, it has the closedElevation property which is used to give the container a drop shadow. To use this, go ahead and update your code to the following:

...
// For OpenContainer
closedElevation: 6,
// For FAB
elevation: 0,
...

In here, we added a closedElevation of 6 to the OpenContainer and removed the elevation of the FAB by setting it to 0. Save your work and try it out. Cool, we can see that the FAB blends in nicely with the OpenContainer animation.