Global UI with Overlays
Ever needed to display a widget above all other content, perhaps a custom notification or a persistent tooltip that isn’t confined to a specific route’s scaffold? Flutter’s Overlay widget is your secret weapon.
Unlike AlertDialogs or regular widget tree additions, Overlays allow you to insert an OverlayEntry directly into the overlay layer, making it appear on top of everything else, regardless of the current route or widget hierarchy.
This is incredibly powerful for building enterprise-grade UIs that require custom global feedback mechanisms, dynamic pop-ups that don’t obscure navigation, or truly “floating” elements.
Remember to manage your OverlayEntry lifecycle carefully — inserting it when needed and removing it when no longer relevant to prevent memory leaks and ensure clean UI.
import 'package:flutter/material.dart';
class OverlayService {
static OverlayEntry? _currentOverlayEntry;
static void showCustomMessage(BuildContext context, String message) {
if (_currentOverlayEntry != null) {
_currentOverlayEntry!.remove();
_currentOverlayEntry = null;
}
_currentOverlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: MediaQuery.of(context).padding.top + 10,
left: 20,
right: 20,
child: Material(
color: Colors.transparent,
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.blueAccent,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.2),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
),
child: Text(
message,
style: const TextStyle(color: Colors.white, fontSize: 16),
textAlign: TextAlign.center,
),
),
),
),
);
Overlay.of(context).insert(_currentOverlayEntry!);
Future.delayed(const Duration(seconds: 3), () {
if (_currentOverlayEntry != null) {
_currentOverlayEntry!.remove();
_currentOverlayEntry = null;
}
});
}
}
Usage in a widget:
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Overlay Demo')),
body: Center(
child: Builder(
builder: (context) {
return ElevatedButton(
onPressed: () {
OverlayService.showCustomMessage(
context,
'Hello from Overlay!',
);
},
child: const Text('Show Overlay Message'),
);
},
),
),
),
),
);
}