Making Custom Hints/Tooltips With OverlayEntry in Flutter

Want to give some type of dialog in response to an action but the provided Tooltip
class just isn’t doing it for you? Maybe it’s time to look at implementing an OverlayEntry
.
What is a tool tip?
A tool tip is generally a static text label that appears over something on your screen that provides more insight into what that something does. Some widgets come out of the box with a tooltip
property that you can set:

For example, a FloatingActionButton
comes with this property and it is shown if a user long-presses on the button:

Without creating a custom FloatingActionButton
, there isn’t much customization available for your tool tip. Side note: if you want to see how to customize a Flutter widget, I wrote an article showing you how to do that here.
You can, however, use the Tooltip
widget directly by wrapping it over another widget. In this case, I wrapped a standard Text
widget with the Tooltip
to create a custom message:
Tooltip( message: "Hi this is the standard tip", child: Text( 'You have pushed the button this many times:', ),),

When you tap and hold on the Text, it displays the message that you set. Using ToolTip
gives you many more options to customize such as its height, style, vertical offset, and duration:

Overriding the default Tooltip
parameters can provide a pretty customized message:

Maybe something above suits your needs, but if you want to add an animation or show the tool tip after a different gesture, we can make our own using OverlayEntry
.
Making our Custom “tool tip”
To make what you see in the top video, follow these steps:
First, we will use a GestureDetector
widget and put a Text
widget as its child. I want this tool tip to appear if the user double taps on the text, so I’m going to include an onDoubleTap
property:

Now, let’s create our actual OverlayEntry
. Create a new .dart file and name it whatever you please (mine is called hint_overlay.dart). In your new file, create a new StatefulWidget and name it according to your needs (mine is called HintOverlay). While you are there, add the SingleTickerProviderStateMixin
implementation (because we need that for the animation) and the initState
and dispose
methods:

We need HintOverlay
to take two parameters:
1. A reference to the OverlayEntry
that HintOverlay
will be inserted into (entry
)
2. A message to be displayed as the hint (message
):

(Obviously you can set as many parameters as you please, but you will see why we need a reference to at least the OverlayEntry
passed in)
I want my tool tip to show via an animation — sliding from the right side of the screen to the left side of the screen, so I’m going to add that AnimationController
and Tween
animation inside the HintOverlay’s initState
:

Additionally, I’m creating a timer (_startTimer
) that will remove the OverlayEntry
after a given time. I’ll start it in initState
and I’ll set its duration to one second higher than what the AnimationController
’s duration is set to, that way it is removed after it is off-screen:

When we call .remove()
on the OverlayEntry
that we passed in (widget.entry), dispose()
will be activated. This is why we pass in that entry
reference.
Back to the main.dart
file, we have to create the actual OverlayEntry
and have that return our new HintOverlay
widget. We will then have our OnDoubleTap
property return our inserted OverlayEntry
.

Now that everything is set up, we can double-tap on the “My Overlay Entry tip” text and our tip should slide across the screen in a marquee-ish style. Here it is again:

This type of tool tip/hint can be used for other purposes, as I use this style with creating notification overlays for “heads-up” chat notifications and the like.
There should be enough here to get you rolling in your own direction. Reach out to me if you need help with any of it.
Final note: Regarding accessibility, you can wrap your widgets with a Semantics widget and set your data with that. You can find more information about accessibility details on the Flutter Accessibility page here.
Here is the full code for both the main.dart
file and the hint_overlay.dart
file (I removed most of the boilerplate Flutter code from main.dart):
Main.dart
hint_overlay.dart