A simple library based on PopupWindow to create customizable tooltips on Android. Android Simple Tooltip is a lightweight and easy-to-use library based on PopupWindow to create flexible, animated tooltips, guided tours, and onboarding hints on Android with a clean, fluent Builder API. 🇧🇷 Documentação em Português Quick Start · Why · Demo · Installation · Usage · Resources · API Reference · Known Issues ·…
A simple library based on PopupWindow to create customizable tooltips on Android.
Android Simple Tooltip is a lightweight and easy-to-use library based on PopupWindow to create flexible, animated tooltips, guided tours, and onboarding hints on Android with a clean, fluent Builder API.
Show a tooltip anchored to any View with a single chained call:
View yourView = findViewById(R.id.your_view);
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text("Welcome to the new feature!")
.gravity(Gravity.BOTTOM)
.animated(true)
.transparentOverlay(false)
.build()
.show();
💡 Why Android Simple Tooltip?
🎯 Fluent Builder Pattern. Configure anchors, gravities, colors, offsets, and callbacks in a single chained statement.
⚡ Lightweight & Independent. Built on standard Android PopupWindow, requiring zero heavy third-party dependencies.
🎬 Smooth Floating Animations. Configurable subtle floating motion with custom duration and translation distance.
🔍 Spotlight Backdrop Overlays. Focus user attention with dimmed backgrounds featuring oval or rounded-rectangular spotlight cutouts.
🎛️ Granular Dismiss Control. Dismiss on touch inside, touch outside, or block background interactions in modal mode.
📐 Customizable Shapes & Arrows. Control arrow dimensions, direction, colors, or substitute your own custom drawable.
🧩 Inflatable Custom Layouts. Inflate complex XML layouts with custom buttons, inputs, and interactive views inside the tooltip.
🎨 Deep Resource Theming. Override styling globally via XML dimensions, colors, and styles without touching Java code.
📸 Demo
Explore the complete sample app in the sample directory.
📦 Installation
1. Configure Repository
Add JitPack to your root build.gradle at the end of repositories:
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text(R.string.tip_text)
.gravity(Gravity.TOP)
.animated(true)
.animationDuration(1000)
.animationPadding(SimpleTooltipUtils.pxFromDp(6))
.build()
.show();
3. Spotlight Backdrop Overlay
Darkens the surrounding screen while highlighting the anchor view with an oval or rounded-rectangular spotlight:
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text("Focus attention on this element")
.gravity(Gravity.START)
.animated(true)
.transparentOverlay(false)
.highlightShape(OverlayView.HIGHLIGHT_SHAPE_RECTANGULAR_ROUNDED)
.cornerRadius(20)
.overlayOffset(0)
.overlayWindowBackgroundColor(Color.BLACK)
.build()
.show();
4. Modal Mode & Dismissal Rules
Prevent users from interacting with the background while the tooltip is visible:
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text("Modal tooltip: tap inside to dismiss")
.gravity(Gravity.BOTTOM)
.modal(true)
.dismissOnInsideTouch(true)
.dismissOnOutsideTouch(false)
.build()
.show();
5. Custom Inflatable XML Layout
Inflate a custom layout with custom views, action buttons, or text fields:
final SimpleTooltip tooltip = new SimpleTooltip.Builder(this)
.anchorView(yourView)
.gravity(Gravity.TOP)
.modal(true)
.animated(true)
.contentView(R.layout.tooltip_custom, R.id.tv_text)
.focusable(true)
.build();
// Access views inside the custom layout
Button btnNext = tooltip.findViewById(R.id.btn_next);
EditText edText = tooltip.findViewById(R.id.ed_text);
btnNext.setOnClickListener(v -> {
tooltip.dismiss();
// Do something with edText.getText()
});
tooltip.show();
6. Custom Arrow Direction & Icon
Customize or remove the indicator arrow:
// Without arrow
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text("No arrow")
.gravity(Gravity.CENTER)
.showArrow(false)
.build()
.show();
// Custom arrow drawable and size
new SimpleTooltip.Builder(this)
.anchorView(yourView)
.text("Custom arrow")
.gravity(Gravity.END)
.arrowDrawable(R.drawable.ic_custom_arrow)
.arrowWidth(SimpleTooltipUtils.pxFromDp(32))
.arrowHeight(SimpleTooltipUtils.pxFromDp(32))
.build()
.show();
7. Inside Dialogs or DialogFragments
When showing tooltips inside a dialog, set overlayMatchParent(false) so the overlay respects the dialog’s bounds:
new SimpleTooltip.Builder(activity)
.anchorView(btnInDialog)
.text("Tip inside a Dialog")
.gravity(Gravity.BOTTOM)
.animated(true)
.transparentOverlay(false)
.overlayMatchParent(false)
.build()
.show();
🎨 Customization & Resources
You can override default styling globally across your app by defining these resources in your project’s res/values/:
Colors (res/values/colors.xml)
<resources><!-- Tooltip bubble background color --><colorname="simpletooltip_background">@color/colorAccent</color><!-- Tooltip default text color --><colorname="simpletooltip_text">@android:color/primary_text_light</color><!-- Indicator arrow color --><colorname="simpletooltip_arrow">@color/colorAccent</color></resources>
<resources><!-- Overlay backdrop darkness (0 to 255) --><integername="simpletooltip_overlay_alpha">120</integer><!-- Duration of one animation cycle in milliseconds --><integername="simpletooltip_animation_duration">800</integer></resources>
Styles (res/values/styles.xml)
Override simpletooltip_default in your app to customize default text appearance (the library style inherits @android:style/TextAppearance.Medium):
<resources><stylename="simpletooltip_default"parent="@android:style/TextAppearance.Medium">
<!-- Example text appearance customizations -->
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/simpletooltip_text</item>
</style></resources>
📚 API Reference
SimpleTooltip.Builder Methods
Method
Type / Parameter
Default
Description
anchorView(View)
View
Required
Target view that the tooltip will point to.
text(CharSequence)
CharSequence
""
Text displayed in the tooltip.
text(@StringRes int)
int
String resource ID for the tooltip text.
gravity(int)
Gravity.TOP / BOTTOM / START / END / CENTER
Gravity.BOTTOM
Side relative to the anchor where the tooltip appears.
animated(boolean)
boolean
false
Enables floating bounce animation (API 11+).
animationDuration(long)
long (ms)
800
Duration of each animation cycle.
animationPadding(float)
float / @DimenRes int
4dp
Travel distance of the animation in pixels.
transparentOverlay(boolean)
boolean
true
When false, darkens the screen backdrop with a spotlight.
highlightShape(int)
OverlayView.HIGHLIGHT_SHAPE_*
OVAL
Shape of the spotlight cutout (OVAL, RECTANGULAR, RECTANGULAR_ROUNDED).
cornerRadius(float)
float
0
Corner radius for rounded rectangular spotlight cutouts.
overlayOffset(float)
float (px)
10dp
Extra spacing between the anchor view and the spotlight cutout edge.
overlayWindowBackgroundColor(int)
@ColorInt int
Color.BLACK
Base color of the darkened backdrop overlay.
overlayMatchParent(boolean)
boolean
true
Set to false for dialogs/fragments so the overlay fits the dialog bounds.
ignoreOverlay(boolean)
boolean
false
Completely skips adding the overlay view to the root view hierarchy.
modal(boolean)
boolean
false
Blocks touch events on background views while the tooltip is open.
dismissOnInsideTouch(boolean)
boolean
true
Dismisses the tooltip when clicked inside its bubble.
dismissOnOutsideTouch(boolean)
boolean
true
Dismisses the tooltip when clicked outside its bubble.
showArrow(boolean)
boolean
true
Whether to display the indicator arrow.
arrowDirection(int)
ArrowDrawable.*
AUTO
Arrow direction (AUTO, TOP, BOTTOM, LEFT, RIGHT).
arrowColor(int)
@ColorInt int
Resource default
Tint color for the default arrow drawable.
arrowDrawable(Drawable)
Drawable / @DrawableRes int
Default shape
Custom drawable used as the indicator arrow.
arrowWidth(float)
float
30dp
Arrow base width in pixels.
arrowHeight(float)
float
15dp
Arrow height in pixels.
contentView(View, int)
View, @IdRes int
Default TextView
Custom view with an optional text view ID.
contentView(@LayoutRes int, int)
int, @IdRes int
Layout resource to inflate with an optional text view ID.
backgroundColor(int)
@ColorInt int
Resource default
Background color of the default content bubble.
textColor(int)
@ColorInt int
Resource default
Text color for the default text view.
maxWidth(float)
float / @DimenRes int
0 (unlimited)
Maximum width constraint for the tooltip bubble.
margin(float)
float / @DimenRes int
10dp
Margin between the anchor view and the tooltip bubble.
padding(float)
float / @DimenRes int
8dp
Internal padding within the tooltip bubble.
focusable(boolean)
boolean
Non-touch: true
Enables keyboard/D-pad navigation focus on non-touch devices.
onDismissListener(listener)
OnDismissListener
null
Callback invoked when the tooltip is dismissed.
onShowListener(listener)
OnShowListener
null
Callback invoked when the tooltip is displayed.
build()
SimpleTooltip
Validates parameters and constructs the SimpleTooltip instance.
SimpleTooltip Instance Methods
Method
Return Type
Description
show()
void
Displays the tooltip on screen anchored to the configured view.
dismiss()
void
Dismisses and cleans up the tooltip, overlay, and animations.
isShowing()
boolean
Returns true if the tooltip popup is currently visible.
findViewById(@IdRes int id)
<T extends View> T
Finds a view within the tooltip’s inflated content layout.
Cause: Occurs if a hosting Activity or Dialog is closed while the tooltip’s floating animation is still running.
Impact: Does not crash or impact app stability. The library automatically catches and cleans up listeners upon dismissal.
android.view.WindowLeaked
Cause: Occurs if tooltip.show() is triggered after the parent Activity has already begun finishing or destroying. Refer to the StackOverflow discussion.
Prevention: Always check !isFinishing() or dismiss the tooltip in your onDestroy() / onStop() lifecycle callback.
PopupWindow.setClippingEnabled on Android 7.0+ (API 24+)
Cause: Beginning in Android Nougat (API 24), the platform modified how PopupWindow clips contents against screen boundaries, which may crop popups near the edges.
Workaround: Adjust margin offsets or refer to Issue #40 for specific boundary handling.
🤝 Contributing
Contributions, bug reports, and pull requests are warmly welcomed!
评论