Adding Micro-Interactions With AnimatedSwitcher
Micro-interactions and animations are key factors in people choosing and continuing to use apps. Thus, adding micro-interactions is important for the success of your app. It hasn’t always been easy, but now with AnimatedSwitcher, you can add a lot of interactivity to your app without investing too much effort.
In this tutorial you’ll learn about:
AnimatedSwitcher, how it works and when to use it.
- Using Key to differentiate widgets.
- Customizing how
AnimatedSwitcherbuilds its layout.
- Building custom transitions between widgets with
- Changing the curves in
AnimatedSwitcherto provide natural interaction in your app.
You’ll work on Quotine, an app that inspires people in their daily routine with quotes. Download the starter project by clicking Download Materials at the top or bottom of the tutorial. Then, open the starter project in VS Code 1.57 or later. You can also use Android Studio, but you’ll have to adapt the instructions below as needed.
Use a recent version of Flutter, 2.0 or above. VS Code should show a notification prompting you to click into it to get the dependencies.
If VS Code doesn’t get the dependencies automatically, then download them manually by opening pubspec.yaml and clicking the get package icon on the top-right corner or by running the command
flutter pub get from the terminal.
Here’s a quick rundown of how the project is set up:
- main.dart: Standard main file required for Flutter projects.
- data.dart: Contains the quotes; think of it as the app’s database for this tutorial’s purpose.
domain.dart: Contains the business logic, the
app: A folder with the
QuotineAppwidget, which is the core of Quotine.
- presentation: Contains two folders: pages, containing all Quotine’s pages, and widgets, containing all the reusable widgets.
Build and run the starter project using the emulator of your preference or even your mobile device. At this point, you’ll see the following:
As you can see, if the quote displayed isn’t to your liking, you can always skip to the next quote. However, if you look closely, switching between quotes doesn’t feel completely natural. Instead, you could say it’s a bit janky. You’ll fix this by adding your own micro-interactions with
Animating With the Right Tools
Before you start coding, it’s important to understand the different animation options provided by the framework.
Flutter has a robust
animation library, and inside you can generally classify animations into two groups: implicit animations and explicit animations.
What does that mean? Well, think of implicit animations as already built-in widgets for different needs. For example,
AnimatedOpacity animates opacity values or
AnimatedList helps animate item addition or removal. In fact, you have a whole list of implicitly animated widgets to choose from.
Explicit animations provide a way for you to control, build and customize the way animations work — for example, coordinating between different animations, repeating your animation in a loop or providing discontinuous effects. As always, Flutter helps you tremendously by adding built-in effects like
SlideTransition, which you’ll use later in this tutorial.
Within the animation library, Flutter also provides a way to handle the duration of your animations. This is key to improving usability: If an animation is too fast, it might be hard to see or dizzying; on the other hand, if it’s too slow, it becomes intrusive and feels like a delay to the user. How to handle duration varies between implicit animations and explicit animations, but Flutter does a good job of making it feel natural for you as a developer.
AnimatedSwitcher can be classified as an implicit animation because it provides a built-in way to transition between two widgets. For example, you can use it to make
Text fade in and out when the content changes. It’s highly customizable, so you can play around with different transitions, durations and ways to build the widgets when doing the transition. Here’s an animation you could easily make with
In Quotine’s case, you’ll use
AnimatedSwitcher to enhance the user experience and add some awesome micro-interactions. From a technical perspective, you’ll combine a little bit of both implicit animations and explicit animations.
Adding Your First AnimatedSwitcher
Start by opening lib/presentation/pages/home_page.dart. Now, change the
child property under
// TODO: Replace QuoteDisplay with an AnimatedSwitcher to the following code:
duration: const Duration(milliseconds: 500),
// TODO: Fix animation bug
Here’s what you just did:
- You wrapped
AnimatedSwitcher. This allows you to transition between quotes without worrying too much about how the app handles the animation — yay, Flutter!
- Then, you’re setting
durationto 500 milliseconds. This makes the transition between widgets slower. It will take 500 milliseconds for the old widget to fade out and will also take the same amount of time for the new widget to fade in.
If you later need to customize the duration of the animation for the widget fading out, you can do it by setting
reverseDuration on your
AnimatedSwitcher. In this particular case, it’s not necessary.
Build and run. You’ll see something like this:
Now, don’t get scared — the changes you made are still there!
AnimatedSwitcher is there, but a small bug with the code you just wrote is affecting your micro-interaction. Don’t worry, you’ll fix this next.
Understanding the Key Problem
So, what’s happening right now? Why isn’t
AnimatedSwitcher working? Actually, it is working, just not in the way you’d expect. Here’s an explanation on the underlying issue you need to fix:
- First, your app renders with
0. This means
QuoteDisplayis being painted with the information of the first quote.
- Then, you tap Skip. This changes
_currentQuote, incrementing it by one inside
setState, triggering a re-render of
- When rendering again,
AnimatedSwitchertries to figure out if the property
childchanged, and… it hasn’t. Well, kind of.
The old widget (from Step 1) and the new widget are both of type
QuoteDisplay and both have the same
key, which is
null in this particular case. Because of this,
AnimatedSwitcher can’t determine if the
child has changed, so it doesn’t do a transition between them. In fact, the framework thinks that they’re the same widget.
So, how can you fix this? It’s actually really simple. Adding a
key property to
AnimatedSwitcher determine if something changed. Replace
// TODO: Fix animation bug with the following code as a property of
Build and run. Here’s what it’ll look like now:
Great job! Quotine is looking awesome right now.