Flutter Login Animation

Implementing super smooth animations in your Flutter App

In this post, I will be taking you through the steps to implement smooth animations in your Flutter app.


Here is a timeline showing all the animations that take place in the app.

The secret behind smooth transition between the login screen and home screen is the fact that the last frame of the login screen matches perfectly with the first frame of the home screen.

Let’s take a closer look at the login screen.

In the login screen, the animation begins when the user clicks on the Sign In button. The button gets squeeze into a circular shape, and the text inside the button is replaced by a “loading” animation. Next, the loading animation inside the button disappears and the button grows in a circular fashion while moving to the center. Once at the center, the button grows rectangularly and covers the entire screen.

Once the entire screen is covered by the button, the app navigates to the Home screen.

Here the initial animation does not need any user input. The Home screen comes on the screen with a “fade” animation. The profile image, the notification bubble, and the “+” button grow on the screen in a circular fashion, while the list vertically slides onto the screen.

When the user clicks on the “+” button, the “+” inside the button disappears and circularly grows in size while moving to the center of the screen. Once at the center, the button now grows rectangularly and covers the entire screen.

Looking at things in a different way, animations can also be divided into Entry Animation and Exit Animation.

The timeline for the Entry Animation is as shown below:

And the timeline for the Exit Animation is this:

Enough theory! Let’s get started with the coding.

Animating the Login Screen

Home Screen Animation

On this screen, the animation starts when the user clicks the Sign In button. The animation in this screen can be broken down in the following parts:

Design the button

Login screen has this button component on it:

Note the width property of the Container widget. This property is going to play an important role in the button’s initial animation where it is squeezed into a circle.

Initial setup prior to building the animation.

We need to tell the app to start the animation only when the user has clicked the Sign In button. For that, we create an AnimationController class that is charged with management all of the Animations.

In simple words, AnimationController controls the animation. This class is one of the big actors of the animation framework in Flutter. It extends the Animation class and adds the bare minimum elements to make it usable. Despite its name, this class is not a controller of the animation object, but of the animation concept.

What AnimationController basically does is that it takes the animation from one double value to another in a specified time.

The basic constructor of an AnimationController looks like this:

AnimationController needs a TickerProvider to obtain their Ticker. If you are creating an AnimationController from a state, then you can use the TickerProviderStateMixin and SingleTickerProviderStateMixin classes to obtain a suitable TickerProvider. The widget test framework WidgetTester object can be used as a ticker provider in the context of tests.

We initialise this constructor inside a initState function:

The only thing we need to focus on here, is the Duration widget. This widget defines the total time which the animations of the Login screen have to occur.

The LoginScreenState is a stateful widget and creates the AnimationController specifying a 3000 milliseconds duration. It plays the animation and builds the non-animating portion of the widget tree. The animation begins when a tap of the button is detected on the screen. The animation runs forward, then backward.

Button Squeeze animation (slowed down)

I have used the Tween class along with the CurvedAnimation widget. Tween specifies the point at which the animation should begin and end. At the beginning of the animation, the width of the button is 320.0 pixels, by the end of the animation the button is reduced to the width of 70.0 pixels. The height of the button remains the same. Duration is defined by the Interval widget which is called inside the CurvedAnimation widget. Interval basically tells the app to squeeze the button into a circle within 250 milliseconds.

Once the button is squeezed into a circle, we need the Sign In text to disappear.

I have used a conditional statement to achieve this. If the width of the button is greater that 75.0 pixels, then the button should contain the Sign In text. Else, the button should contain a CircularProgressIndicator.

Loading Animation (slowed down)

Next, I want the button component to zoom out. To do this, simply create a Tween widget that will tell the button to grow from 70.0 pixels to 1000.0 pixels.

But the Tween in itself cannot animate the button. For that we need to use animate() to link the Tween with a CurvedAnimation widget, which contains an Interval widget which tells the app to complete the animation between 350 milliseconds.

Button Grow Animation (Slowed Down)

We also need to simultaneously remove the CircularProgressIndicator from the button. For that we again make use of conditional statements.

While the buttonZoomOut.value is equal to 70, the buttonSqueezeAnimation will work. And when the Interval from the above code snippet goes above 0.550, buttonSqueezeAnimation stops and the buttonZoomOut animation begins.

Similarly, if buttonZoomOut is still at 70.0 pixels, then the height is changed to 60.0 pixels. Else, the height is also made equal to buttonZoomOut’s value.

Now if the buttonZoomOut.value is less that 300.0, then we keep the CircularProgressIndicator inside the button. Else, we replace it with a null.

Here is the code for it:

Finally, we want the button container to grow and cover the entire screen. For this we will first remove the padding(top and bottom) of the whole page and radius of the container should also be negligible. The button should now grow and cover the entire screen with a color transition animation.

Cover Screen Animation (slowed down)

Once the animation is complete, the user is navigated to the home screen.

This is the secret to the smooth transition between the two screen. We need the last frame of the Login screen to match with the first frame of the Home screen. I have also added a listener that waits till the button component has completely covered the entire screen. Once that is done, I have used Flutter’s in-built Navigator to take us to the Home screen.

Animating the Home Screen

Just like the Login screen, animation on the home screen can be broken down into the following parts:

Home Screen Animation (Slowed down)

From the GIF shown above, we can see that when the app navigates to the home screen, the very first thing that happens is that the screen fades to white.

Fade the Screen

Fade Screen Animation (Slowed Down)

To do this, we create a new ColorTween widget and name it as fadeScreenAnimation. Inside this widget, we change the opacity from 1.0 to 0.0, making the color dissappear. We link this widget to CurvedAnimation using animate().

Next we create a new widget called FadeBox and call the fadeScreenAnimation inside it.

Here, the Hero is a widget of Flutter that is used to create hero animations. This animation makes an object “fly” from one screen to another. Any children added to this widget will be qualified for hero animations.

The profile image, notification bubble and the add button grow up in a circular fashion.

All the elements in the top half of the screen take their respective positions. As the profile image and list tiles grow, they animate vertically and take their positions.

List and “+” button animation (slowed down)

With this, the Home Screen is rendered on the screen. Now lets take a look at the animations which will take the user back to the Login Screen.

When the user clicks the Add button, the AnimationController is initialised:

The button navigates from the bottom right of the screen to the center

Button grow animation (slowed down)

While the button is moving to the center of the screen, it slowly grows in size and the Icon disappears.

When the button reaches the center, it is zoomed out in a circular manner, gets converted into a rectangle and covers the whole screen.

Cover screen animation (slow speed)

Finally, once the animation is complete, the app needs to navigate back to the login screen.

This article is written by Rajat S and Ruchika Gupta. Rajat is currently working at GeekyAnts as a Technical Content Writer, while Ruchika is also at GeekyAnts as a Software Developer and created this Flutter Login Animation App.

Thanks to Sanket Sahu for all the help and support that he gave us while writing this post.

And thanks to you for reading! I hope you found this post to be helpful. Please 👏 if you liked this article.