'how to draw over other apps in flutter?
Solution 1:[1]
you can check this plugin system_alert_window
A flutter plugin to show Truecaller like overlay window, over all other apps along with callback events.
Solution 2:[2]
Add this in your pubspec file
dependencies:
system_alert_window: ^0.3.2+1
Run
flutter pub get
import in your dart code
import 'package:system_alert_window/system_alert_window.dart';
Example code taken from here
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:system_alert_window/system_alert_window.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown';
bool _isShowingWindow = false;
bool _isUpdatedWindow = false;
@override
void initState() {
super.initState();
_initPlatformState();
_checkPermissions();
SystemAlertWindow.registerOnClickListener(callBack);
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> _initPlatformState() async {
String platformVersion;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
platformVersion = await SystemAlertWindow.platformVersion;
} on PlatformException {
platformVersion = 'Failed to get platform version.';
}
// If the widget was removed from the tree while the asynchronous platform
// message was in flight, we want to discard the reply rather than calling
// setState to update our non-existent appearance.
if (!mounted) return;
setState(() {
_platformVersion = platformVersion;
});
}
Future<void> _checkPermissions() async {
await SystemAlertWindow.checkPermissions;
}
void _showOverlayWindow() {
if (!_isShowingWindow) {
SystemWindowHeader header = SystemWindowHeader(
title: SystemWindowText(text: "Incoming Call", fontSize: 10, textColor: Colors.black45),
padding: SystemWindowPadding.setSymmetricPadding(12, 12),
subTitle: SystemWindowText(text: "9898989899", fontSize: 14, fontWeight: FontWeight.BOLD, textColor: Colors.black87),
decoration: SystemWindowDecoration(startColor: Colors.grey[100]),
button: SystemWindowButton(text: SystemWindowText(text: "Personal", fontSize: 10, textColor: Colors.black45), tag: "personal_btn"),
buttonPosition: ButtonPosition.TRAILING);
SystemWindowBody body = SystemWindowBody(
rows: [
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Some body", fontSize: 12, textColor: Colors.black45),
),
],
gravity: ContentGravity.CENTER,
),
EachRow(columns: [
EachColumn(
text: SystemWindowText(text: "Long data of the body", fontSize: 12, textColor: Colors.black87, fontWeight: FontWeight.BOLD),
padding: SystemWindowPadding.setSymmetricPadding(6, 8),
decoration: SystemWindowDecoration(startColor: Colors.black12, borderRadius: 25.0),
margin: SystemWindowMargin(top: 4)),
], gravity: ContentGravity.CENTER),
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Notes", fontSize: 10, textColor: Colors.black45),
),
],
gravity: ContentGravity.LEFT,
margin: SystemWindowMargin(top: 8),
),
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Some random notes.", fontSize: 13, textColor: Colors.black54, fontWeight: FontWeight.BOLD),
),
],
gravity: ContentGravity.LEFT,
),
],
padding: SystemWindowPadding(left: 16, right: 16, bottom: 12, top: 12),
);
SystemWindowFooter footer = SystemWindowFooter(
buttons: [
SystemWindowButton(
text: SystemWindowText(text: "Simple button", fontSize: 12, textColor: Color.fromRGBO(250, 139, 97, 1)),
tag: "simple_button",
padding: SystemWindowPadding(left: 10, right: 10, bottom: 10, top: 10),
width: 0,
height: SystemWindowButton.WRAP_CONTENT,
decoration: SystemWindowDecoration(startColor: Colors.white, endColor: Colors.white, borderWidth: 0, borderRadius: 0.0),
),
SystemWindowButton(
text: SystemWindowText(text: "Focus button", fontSize: 12, textColor: Colors.white),
tag: "focus_button",
width: 0,
padding: SystemWindowPadding(left: 10, right: 10, bottom: 10, top: 10),
height: SystemWindowButton.WRAP_CONTENT,
decoration: SystemWindowDecoration(
startColor: Color.fromRGBO(250, 139, 97, 1), endColor: Color.fromRGBO(247, 28, 88, 1), borderWidth: 0, borderRadius: 30.0),
)
],
padding: SystemWindowPadding(left: 16, right: 16, bottom: 12),
decoration: SystemWindowDecoration(startColor: Colors.white),
buttonsPosition: ButtonPosition.CENTER);
SystemAlertWindow.showSystemWindow(
height: 230,
header: header,
body: body,
footer: footer,
margin: SystemWindowMargin(left: 8, right: 8, top: 200, bottom: 0),
gravity: SystemWindowGravity.TOP);
setState(() {
_isShowingWindow = true;
});
} else if (!_isUpdatedWindow) {
SystemWindowHeader header = SystemWindowHeader(
title: SystemWindowText(text: "Outgoing Call", fontSize: 10, textColor: Colors.black45),
padding: SystemWindowPadding.setSymmetricPadding(12, 12),
subTitle: SystemWindowText(text: "8989898989", fontSize: 14, fontWeight: FontWeight.BOLD, textColor: Colors.black87),
decoration: SystemWindowDecoration(startColor: Colors.grey[100]),
button: SystemWindowButton(text: SystemWindowText(text: "Personal", fontSize: 10, textColor: Colors.black45), tag: "personal_btn"),
buttonPosition: ButtonPosition.TRAILING);
SystemWindowBody body = SystemWindowBody(
rows: [
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Updated body", fontSize: 12, textColor: Colors.black45),
),
],
gravity: ContentGravity.CENTER,
),
EachRow(columns: [
EachColumn(
text: SystemWindowText(text: "Updated long data of the body", fontSize: 12, textColor: Colors.black87, fontWeight: FontWeight.BOLD),
padding: SystemWindowPadding.setSymmetricPadding(6, 8),
decoration: SystemWindowDecoration(startColor: Colors.black12, borderRadius: 25.0),
margin: SystemWindowMargin(top: 4)),
], gravity: ContentGravity.CENTER),
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Notes", fontSize: 10, textColor: Colors.black45),
),
],
gravity: ContentGravity.LEFT,
margin: SystemWindowMargin(top: 8),
),
EachRow(
columns: [
EachColumn(
text: SystemWindowText(text: "Updated random notes.", fontSize: 13, textColor: Colors.black54, fontWeight: FontWeight.BOLD),
),
],
gravity: ContentGravity.LEFT,
),
],
padding: SystemWindowPadding(left: 16, right: 16, bottom: 12, top: 12),
);
SystemWindowFooter footer = SystemWindowFooter(
buttons: [
SystemWindowButton(
text: SystemWindowText(text: "Updated Simple button", fontSize: 12, textColor: Color.fromRGBO(250, 139, 97, 1)),
tag: "updated_simple_button",
padding: SystemWindowPadding(left: 10, right: 10, bottom: 10, top: 10),
width: 0,
height: SystemWindowButton.WRAP_CONTENT,
decoration: SystemWindowDecoration(startColor: Colors.white, endColor: Colors.white, borderWidth: 0, borderRadius: 0.0),
),
SystemWindowButton(
text: SystemWindowText(text: "Focus button", fontSize: 12, textColor: Colors.white),
tag: "focus_button",
width: 0,
padding: SystemWindowPadding(left: 10, right: 10, bottom: 10, top: 10),
height: SystemWindowButton.WRAP_CONTENT,
decoration: SystemWindowDecoration(
startColor: Color.fromRGBO(250, 139, 97, 1), endColor: Color.fromRGBO(247, 28, 88, 1), borderWidth: 0, borderRadius: 30.0),
)
],
padding: SystemWindowPadding(left: 16, right: 16, bottom: 12),
decoration: SystemWindowDecoration(startColor: Colors.white),
buttonsPosition: ButtonPosition.CENTER);
SystemAlertWindow.updateSystemWindow(
height: 230,
header: header,
body: body,
footer: footer,
margin: SystemWindowMargin(left: 8, right: 8, top: 200, bottom: 0),
gravity: SystemWindowGravity.TOP);
setState(() {
_isUpdatedWindow = true;
});
} else {
setState(() {
_isShowingWindow = false;
_isUpdatedWindow = false;
});
SystemAlertWindow.closeSystemWindow();
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('System Alert Window Example App'),
),
body: Center(
child: Column(
children: <Widget>[
Text('Running on: $_platformVersion\n'),
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: MaterialButton(
onPressed: _showOverlayWindow,
textColor: Colors.white,
child: !_isShowingWindow
? Text("Show system alert window")
: !_isUpdatedWindow ? Text("Update system alert window") : Text("Close system alert window"),
color: Colors.deepOrange,
padding: const EdgeInsets.symmetric(vertical: 8.0),
),
)
],
),
),
),
);
}
}
///
/// Whenever a button is clicked, this method will be invoked with a tag (As tag is unique for every button, it helps in identifying the button).
/// You can check for the tag value and perform the relevant action for the button click
///
void callBack(String tag) {
print(tag);
switch (tag) {
case "simple_button":
case "updated_simple_button":
SystemAlertWindow.closeSystemWindow();
break;
case "focus_button":
print("Focus button has been called");
break;
default:
print("OnClick event of $tag");
}
}
Solution 3:[3]
You can use flutter_overlay_apps plugin. Here is an example code from documentation example;
// overlay entry point
@pragma("vm:entry-point")
void showOverlay() {
runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: Material(child: Text("My overlay"))
));
}
or simply
// overlay entry point
@pragma("vm:entry-point")
void showOverlay() {
runApp(MyWidget());
}
Solution 4:[4]
You can use flutter_overlay_window. Its JAVA only but works fine. The example app has a truecaller like overlay demo.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | griffins |
Solution 2 | Vamsi |
Solution 3 | Edie Kamau |
Solution 4 | Sudipta Roy |