Flutter: Adding Animated Overlays to Your App
This is the second part of my tutorial about
BottomAppBar and FAB (part one is here). Today we will see how to reveal options when the FAB if pressed.
We will see how to add overlays in Flutter, and why this is a valuable technique that you can add to your toolbox.
Revealing buttons when FAB is pressed
In this tutorial we will add the code to enable the following animation:
The animation itself was originally taken from this example on StackOverflow.
I have bundled the example code into
FabWithIcons, a new custom widget that we can assign directly to our
How does this work?
- Line 4: We define
StatefulWidgetas it needs an
AnimationControllerto manage the animation state.
- Lines 5 to 7: We pass a list of icons and a callback for when an icon is tapped. This is of type
ValueChanged<int>so that we can specify the index of the icon that was tapped.
- Lines 12 to 22: We add a
TickerProviderStateMixinto our state class, and initialise an
vsyncparameter. For a good overview of the animation APIs see this article about Flutter animations by Sergi & Replace.
- Lines 25 to 35: In our
buildmethod, we generate a list of icons, and append a
FloatingActionButtonas the last element.
- Lines 37 to 61: We define a small (
FloatingActionButtonfor the item at a given index, and link a
ScaleTransitionwidget to our animation controller. This is what makes the FABs animate in and out.
- Lines 63 to 76: We create the main FAB, and use the
onPressedhandler to update our animation controller as needed.
- Lines 78 to 81: When an option is selected, we hide all the icons (via
_controller.reverse()), and notify the parent that an item has been selected.
Let’s try to use this.
In our main page, we add this method to create a FAB with three icons:
Then, we can call it like so inside our
If we run the app, we see that this does not look right. However, if we comment out the
floatingActionButtonLocation line in our
Scaffold, the FAB moves to the default location and no longer interferes with our
What is going on here?
FABWithIcons is taller than a normal FAB because it has additional icons. Trying to fit this as a docked item in a
BottomAppBar does not work well. I suspect the Flutter SDK tries to compensate for the extra height by pushing the FAB all the way to the bottom, but this results in a visual artifact.
What to do?
What if we could use a standard FAB as a single widget in our
BottomAppBar, but switch to a completely separate layer when we need to show the extra icons?
Flutter offers a widget called
Overlay which is great for this scenario. From the documentation of the
A Stack of entries that can be managed independently.
Overlays let independent child widgets “float” visual elements on top of other widgets by inserting them into the overlay’s Stack. The overlay lets each of these widgets manage their participation in the overlay using
This sounds like what we need. But how do we use it?
The SDK documentation reveals that we need to create an
OverlayEntry object so that we can hold our custom
FABWithIcons. We can do this by defining this method:
However, this is some imperative code, while our application UI is defined declaratively. How do we reconcile the two?
It turns out that getting overlays to work requires quite a bit of work, and implementing them correctly is not straightforward.
For the purposes of our tutorial, we are going to borrow and use some of his code. Here is the entire Overlay layout code:
Matt explains this code in great detail on his video.
Here, I just show how to use it for our purposes.
Bottom line: we can update our
_buildFab method as follows:
This code uses
AnchoredOverlay to build a separate overlay for our
CenterAbout is used to position our overlay relative to the location of the FAB. To position our
FabWithIcons correctly, we offset it by the number of icons, times the size of each icon (35 pt).
Note: On line 4, we pass
showOverlay: true. This is so that the FAB in the overlay is always visible and stacked exactly above the main FAB in the
BottomAppBar. This is ok because the original FAB and the one inside
FABWithIcons look identical when the icons are hidden.
If you use
AnchoredOverlay to build your own UIs, you could hold a state variable for the
showOverlay parameter, and toggle this as needed.
We have seen how to show our custom UI with animations as an overlay, so that we can dock our custom FAB inside a
BottomAppBar without problems.
With the layout helpers provided, adding overlays to your app becomes very easy:
- Move all your overlay UI code into a custom widget class.
- Wrap your desired widget inside an
CenterAboutto position your overlay relative to the original widget.
I open sourced my full example here on GitHub. 🙏
Feel free to reuse it in your projects. 😎