Flutter Overlay Support
A lightweight, powerful, and intelligent overlay support package for Flutter. Build premium notifications, toasts, and popovers with a high-level declarative API.
🚀 Key Features in Depth
📥 Smart Overlay Queue
Intelligent management of multiple overlays. Most packages show overlays immediately, causing them to overlap and clutter the screen.
- Prioritization: 5 levels (
low,normal,high,urgent,critical). Critical items jump to the front. - Deduplication: Use
idandQueueStrategyto replace or ignore duplicate notifications. - Serialization: Overlays wait for the previous one to finish before showing.
- Control: Pause, resume, or clear the queue at any time.
⚓ Widget Anchoring
Go beyond fixed top/bottom notifications. Attach overlays directly to any widget in your tree.
- GlobalKey Tracking: Pass a
targetKeyand the overlay will automatically find its position. - Dynamic Following: The overlay stays attached to the widget even as the user scrolls.
- Auto-Flipping: If an overlay is set to show at the
topbut hits the screen edge, it automatically flips to thebottom. - Arrow Support: Built-in arrows that point exactly to the target widget.
⚡ Future & Progress API
Declarative way to handle asynchronous operations.
showFuture: Handles the full lifecycle of a Future. Shows a loader, then automatically replaces it with a success or error notification.showProgress: Returns a handle that you can use to push live updates (e.g., "Downloading 45%...") without flickering.
🎨 Adaptive UI & Themes
Automatically looks "correct" on every platform.
- Platform Awareness: Native look for Android (Material 3), iOS/macOS (Cupertino), and Windows (Fluent).
- Premium Factories: Quickly apply
glassmorphism(),neon(), orminimal()styles globally. - Glassmorphism: Built-in support for real-time background blurring that respects light/dark modes.
🎮 Lifecycle & Control
Complete programmatic control over every overlay.
- Entry Handles: Capture an
OverlaySupportEntryto manuallydismiss()orupdate()an active overlay. - Event Hooks: Use
onShow,onDismiss, andonTapto trigger app logic when users interact with notifications.
🔍 Debug Inspector
During development, show the OverlayInspector to visualize all active/queued overlays and their keys. Never lose track of "leaked" overlays again.
🔥 Why use Flutter Overlay Support?
| Feature | Standard SnackBars | Other Packages | Flutter Overlay Support |
|---|---|---|---|
| Queue Management | ❌ None | ⚠️ Simple | ✅ Smart Priority Queue |
| Overlap Prevention | ❌ No | ⚠️ Sometimes | ✅ Built-in & Automatic |
| Widget Anchoring | ❌ No | ❌ No | ✅ Dynamic Follow & Flip |
| Future/Async API | ❌ Manual | ❌ Manual | ✅ Declarative showFuture |
| Adaptive Design | ❌ Static | ❌ Static | ✅ Platform-Aware UI |
| Dependencies | ✅ None | ⚠️ Often many | ✅ Pure Flutter (Zero) |
🛠 Getting Started
Installation
Add this to your pubspec.yaml:
dependencies:
flutter_overlay_support: ^1.0.0
Import
import 'package:flutter_overlay_support/flutter_overlay_support.dart';
Initialization (Optional but Recommended)
The easiest way to use the library is to wrap your MaterialApp with OverlaySupport.global. This enables the global API (toast, showSimpleNotification, etc.) to work from anywhere in your code without needing a BuildContext.
OverlaySupport.global(
theme: OverlaySupportThemeData.material3(),
child: MaterialApp(
home: HomePage(),
),
)
Alternative (Scoped):
If you don't want to wrap your entire app, you can use OverlaySupport.local to limit overlays to a specific subtree, or pass a context to every API call:
showSimpleNotification(Text("Hello"), context: context);
📖 Usage Examples
Using the Intelligent Queue
showSimpleNotification(
Text("Critical Update"),
useQueue: true,
priority: OverlayPriority.critical,
id: "update_notice",
strategy: QueueStrategy.replace, // Replace if already in queue
);
Anchoring to a Button
final anchorKey = GlobalKey();
ElevatedButton(key: anchorKey, child: Text("Menu"), ...);
showAnchorOverlay(
targetKey: anchorKey,
preferredAlignment: AnchorAlignment.bottomCenter,
child: MyCustomMenu(),
);
Declarative Future API
// The loader shows automatically, then disappears when the future finishes.
await showFuture(
future: myApiCall(),
loading: "Saving...",
success: "Saved!",
error: "Error occurred",
);
Live Progress Updates
final progress = showProgress(0, message: "Downloading...");
// Update from anywhere
progress.update(0.5, message: "Halfway there...");
// Complete with a final message (auto-dismisses after 1s)
progress.complete(message: "Download Finished!");
Global Group Control
// Tag notifications with a group
showSimpleNotification(Text("File 1 uploaded"), group: "uploads");
showSimpleNotification(Text("File 2 uploaded"), group: "uploads");
// Dismiss only the upload notifications
dismissOverlayGroup("uploads");
Lifecycle Hooks & Manual Control
final entry = showSimpleNotification(
Text("Interactive Notification"),
onTap: () => print("Tapped!"),
onDismiss: () => print("Gone!"),
autoDismiss: false,
);
// Later in your logic
entry.dismiss();
Debugging with Inspector
// Show a list of all active overlays during development
showModalBottomSheet(
context: context,
builder: (context) => const OverlayInspector(),
);
🛠 API Reference
Notifications & Toasts
toast(message, {duration, context}): Quick, simple text toast.showSimpleNotification(content, {leading, subtitle, trailing, background, foreground, position, useQueue, ...}): High-level API for standard notifications.showOverlayNotification(builder, {duration, position, useQueue, ...}): Show any custom widget as a sliding notification.
Specialized Overlays
showAnchorOverlay({targetKey, child, preferredAlignment, showArrow, ...}): Attach an overlay to a specific widget.showFuture({future, loading, success, error, ...}): Declarative way to handle async operation lifecycles.showProgress(initialValue, {message, ...}): Returns aProgressEntryhandle for live updates.showLoading({message, indicator, ...}): Show a manual loading overlay.showOverlay(builder, {curve, duration, useQueue, id, strategy, ...}): The base API for full control over any overlay.
Global & Group Controls
dismissAllOverlays({animate, context}): Instantly clear all active overlays.dismissOverlayGroup(group, {animate, context}): Dismiss all overlays belonging to a specific group.pauseOverlayQueue(): Temporarily stop showing new queued overlays.resumeOverlayQueue(): Resume processing and showing items in the queue.
Overlay Handles (OverlaySupportEntry)
Captured when you show any overlay:
entry.dismiss({animate}): Manually remove the overlay.entry.complete(): Alias for dismiss (Promise-like API).entry.update(): Trigger a rebuild of the overlay content.entry.dismissed: AFuturethat completes when the overlay is gone.
📜 License
MIT License. See LICENSE for details.