A few weeks ago I shared a gif on my Twitter showing a really simple yet cool animation for a fictional app. The animation in question consists of two parts, the translation of elements from the bottom of the screen to their final position and the change in opacity as elements appear on the screen. In this article, I am going to cover how it was made.
Setup / Planning
Before we start coding, there are a few things we must consider. Let’s start by actually creating a new Flutter project and downloading the assets. If you are new, you can create a new Flutter project using the following command:
flutter create <your-awesome-project>
As for assets, we are going to need a header image. I chose a stock picture of New York from www.pexels.com.
Time to plan our animation. If we look at the gif, we immediately notice three distinct features:
- The translation of the elements
As you can see the different elements are using staggered animations, so that they fly in one after another.
Below is a timeline of the different animations:
From the image, we can clearly see the different animations and their associated time slots.
Before animating anything, let’s first define our static layout. The code below consist of basic theming and layout for our widgets. Running the code below will generate an image followed by dummy text and a button at the bottom of the screen.
With the main layout of our application defined, we can start working on the fun parts!
Setting up our Animation
There are a few different methods we can use to animate the app. The first and most obvious method would be to use an
AnimationController. In our case, we're going to do something different, instead of setting up our own
AnimationController, we are going to use the animation provided by the route. The reason for using the route animation is that it is automatically reversed when the user navigates to the previous page. A the user navigates to the page, the animation value goes from
1.0. When they leave, the animation value goes from
For this, there are two small addition we need to make to our existing code. First, in
MaterialApp, we will use
onGenerateRoute to return our app screen.
We check whether the route being pushed onto the Navigator is the first route. If it is the first route, we then call
AnimationsPlayground.route();. This step is only necessary since we only have one page and would like to use our custom route. For a multi page application, we can simply use:
To define our custom route, open
AnimationsPlayground and add the following:
As you might have guessed, we are simply manually building the page with a custom transition duration (six seconds).
With our animation configured, we can move on to the next step, animating widgets!
Let’s start by defining our various animations. As we discussed earlier, there are three key steps this animation: translation, fade/opacity and timing.
The above snippet define animations for translation and opacity of our various widgets. Notice the difference in types, our translation
Animation defines an
Offset while our opacity and controller expects
Since we are using the animation provided by the route, we need to override
didChangeDependencies so that the animation for the given
ModalRoute may be accessed via the
context. If you are wondering why we are not using
initState(), it is because context is not available in
controller variable we defined is null, the value from
ModalRoute is used. Next we can start defining our Tweens. Let's start by defining the translation tween for the header image:
So what is going on here? We are using a Tween to specify a start and end value. We are then using a
CurvedAnimation and an
Interval to animate our
Tween. The values passed to
Interval represent the start and end percentage of the animation. Here, we are starting at 0.0s and ending at 67% or approximately 4 seconds into the total animation.
Now, we can define the remaining
With our Tweens now defined, the final step is to wire them to our static widgets. Let’s navigate to the build method of
_CoolAnimatedAppState and wrap our
Column in an
AnimatedBuilder. Animated Builder requires an animation so for this we are going to pass it our
controller variable. Next, we need to wrap our widgets in a widget which allows it to animate its position. There are many widgets we can use for this but to keep things simple, we are going to use
FractionalTranslation. Fractional Translation moves it's child fractionally in relation to its parent. For example, if the parent defines a height of
200 pixel and you apply a
0.25 translation, then the child will be moved to
50 pixel or a quarter of the height of the parent.
The snippet above shows our widget tree with
FractionalTranslation added. Note the value being passed for
translation is the value of the corresponding variable (Tween). I refactored the three main components into their own
StatelessWidgets to make the code a bit shorter and easier to read.
Last but not least is the fade animation. For this, we are again going to keep this relatively simple and use a
FadeTransition. Let's update our code so that the child of our
FractionalTranslation is a
FadeTransition. Again we pass the corresponding
Tween for the opacity value of our
Now if we hot restart our app, we should hopefully see our animation!
Like I mentioned at the start of this article, there are many different ways this can be done. You don’t need to use the route animation if you don’t want to, you could’ve easily defined an
AnimationController with a duration. My goal for this tutorial was to demonstrate how to build a really simple yet cool looking animation in a short space of time and with minimal effort. The advantage of using the animation provided by the
ModalRoute is that it is automatically reversed when the user leaves the page, saving us the trouble of manually handling that scenario. If you’d like to learn more about Route animation, be sure to follow Flutter Community on Medium, we’ll have a more in depth guide to route animations sometime in the near future.
If you enjoyed this article, be sure to 👏 and share. If you’d like to see more cool apps and projects, be sure to follow Flutter Community and myself on Twitter. The final source code for this project is available on my GitHub at https://github.com/Nash0x7E2/page_load_animation.