Flutter plugin for displaying your Flutter app over other apps on the screen
| TrueCaller overlay example | click-through overlay example | Messanger chat-head example |
|---|---|---|
![]() |
![]() |
![]() |
Add package to your pubspec:
dependencies:
flutter_overlay_window: any # or the latest version on PubYou'll need to add the SYSTEM_ALERT_WINDOW permission and OverlayService to your Android Manifest.
Replace explanation_for_special_use with your custom explanation.
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application>
...
<service android:name="flutter.overlay.window.flutter_overlay_window.OverlayService"
android:exported="false"
android:foregroundServiceType="specialUse">
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="explanation_for_special_use"/>
</service>
</application>Inside main.dart create an entry point for your Overlay widget;
// overlay entry point
@pragma("vm:entry-point")
void overlayMain() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: Material(child: Text("My overlay"))
));
}
/// check if overlay permission is granted
final bool status = await FlutterOverlayWindow.isPermissionGranted();
/// request overlay permission
/// it will open the overlay settings page and return `true` once the permission granted.
final bool status = await FlutterOverlayWindow.requestPermission();
/// Open overLay content
///
/// - Optional arguments:
///
/// `height` the overlay height and default is [WindowSize.fullCover]
///
/// `width` the overlay width and default is [WindowSize.matchParent]
///
/// `alignment` the alignment postion on screen and default is [OverlayAlignment.center]
///
/// `visibilitySecret` the detail displayed in notifications on the lock screen and default is [NotificationVisibility.visibilitySecret]
///
/// `OverlayFlag` the overlay flag and default is [OverlayFlag.defaultFlag]
///
/// `overlayTitle` the notification message and default is "overlay activated"
///
/// `overlayContent` the notification message
///
/// `enableDrag` to enable/disable dragging the overlay over the screen and default is "false"
///
/// `dismissConfig` an `OverlayDismissConfig` that enables drag-to-dismiss: a target appears at the bottom
/// of the screen during drag, dropping the overlay on it closes the overlay. Default is null (disabled)
///
/// `positionGravity` the overlay postion after drag and default is [PositionGravity.none]
///
/// `startPosition` the overlay start position and default is null
///
/// `notificationIcon` name of a drawable/mipmap resource in your app used as the notification icon, default is the launcher icon
await FlutterOverlayWindow.showOverlay();
/// closes overlay if open
await FlutterOverlayWindow.closeOverlay();
/// broadcast data to and from overlay app
await FlutterOverlayWindow.shareData("Hello from the other side");
/// streams message shared between overlay and main app
FlutterOverlayWindow.overlayListener.listen((event) {
log("Current Event: $event");
});
/// use [OverlayFlag.focusPointer] when you want to use fields that show keyboards
await FlutterOverlayWindow.showOverlay(flag: OverlayFlag.focusPointer);
/// update the overlay flag while the overlay in action
await FlutterOverlayWindow.updateFlag(OverlayFlag.defaultFlag);
/// Update the overlay size in the screen
await FlutterOverlayWindow.resizeOverlay(80, 120);
/// Update the overlay position in the screen
///
/// `position` the new position of the overlay
///
/// `return` true if the position updated successfully
await FlutterOverlayWindow.moveOverlay(OverlayPosition(0, 156))
/// Get the current overlay position
///
/// `return` the current overlay position
await FlutterOverlayWindow.getOverlayPosition()
/// Update the notification while the overlay is showing (only the given values change)
///
/// `icon` name of a drawable/mipmap resource, e.g. res/drawable/ic_stat_overlay.png -> "ic_stat_overlay"
///
/// `return` false if no overlay is active
await FlutterOverlayWindow.updateNotification(title: "Recording", content: "00:42", icon: "ic_stat_overlay")Enable a dismiss zone that appears at the bottom of the screen while dragging the overlay. Dropping the overlay on it closes it.
/// Basic usage — built-in X-in-circle target
await FlutterOverlayWindow.showOverlay(
enableDrag: true,
dismissConfig: const OverlayDismissConfig(),
);
/// Customized built-in target
await FlutterOverlayWindow.showOverlay(
enableDrag: true,
dismissConfig: const OverlayDismissConfig(
size: 64,
bottomMargin: 48,
shape: OverlayDismissShape.rectangle,
borderRadius: 16,
backgroundColor: Color(0xCC333333),
activeBackgroundColor: Colors.red, // while the overlay is over the target
iconColor: Colors.white,
iconSize: 24,
iconStrokeWidth: 3,
borderWidth: 2,
borderColor: Colors.white24,
activeBorderColor: Colors.white,
activeScale: 1.25,
hapticFeedback: true,
),
);
/// Custom drawable resource
/// Place your icon in android/app/src/main/res/drawable/ (e.g. ic_dismiss.xml)
/// and pass the resource name without the extension:
await FlutterOverlayWindow.showOverlay(
enableDrag: true,
dismissConfig: const OverlayDismissConfig(icon: "ic_dismiss"),
);| Option | Default | Description |
|---|---|---|
icon |
null |
Drawable/mipmap resource used instead of the built-in X |
size |
56 |
Width and height of the target (dp) |
bottomMargin |
40 |
Distance from the bottom of the screen (dp) |
shape |
circle |
OverlayDismissShape.circle or .rectangle |
borderRadius |
12 |
Corner radius for rectangle (dp) |
backgroundColor / activeBackgroundColor |
Color(0xCC333333) |
Fill color, normal / while hovered |
iconColor / activeIconColor |
Colors.white |
X color, normal / while hovered |
iconSize |
22 |
Size of the X (dp) |
iconStrokeWidth |
4 |
Stroke width of the X (dp) |
borderWidth |
0 |
Border width, 0 for none (dp) |
borderColor / activeBorderColor |
transparent | Border color, normal / while hovered |
activeScale |
1.2 |
Scale applied while hovered, 1 to disable |
hapticFeedback |
true |
Vibrate when the overlay enters the target |
When icon is set and found in the app's drawable or mipmap resources, it replaces the built-in target. The shape, color, border and icon options only apply to the built-in target; size, bottomMargin, activeScale and hapticFeedback apply to both.
enum OverlayFlag {
/// Window flag: this window can never receive touch events.
/// Usefull if you want to display click-through overlay
clickThrough,
/// Window flag: this window won't ever get key input focus
/// so the user can not send key or other button events to it.
defaultFlag,
/// Window flag: allow any pointer events outside of the window to be sent to the windows behind it.
/// Usefull when you want to use fields that show keyboards.
focusPointer,
}
/// Type of dragging behavior for the overlay.
enum PositionGravity {
/// The `PositionGravity.none` will allow the overlay to postioned anywhere on the screen.
none,
/// The `PositionGravity.right` will allow the overlay to stick on the right side of the screen.
right,
/// The `PositionGravity.left` will allow the overlay to stick on the left side of the screen.
left,
/// The `PositionGravity.auto` will allow the overlay to stick either on the left or right side of the screen depending on the overlay position.
auto,
}



