What’s the best way to blur a Flutter app when is not active? The similar way like iOS is doing with the Camera app.
Asked
Active
Viewed 2,480 times
2
-
2You should be able to detect when the app is about to go into the background and take action just before it does. I have not tested this, but theoretically, you could apply a filter view over your app or maybe even redirect so that the OS screenshot for multitasking captures the blurred screen instead of whatever the user was on when they exited the app. – daddygames Oct 13 '21 at 20:45
-
@daddygames Tested it, it doesn't work for the first time the app goes inactive/paused (while the app does get blurred, it shows it momentarily, it goes back to normal) however all the other times you open the app drawer the app gets blurred. – esentis Oct 13 '21 at 21:51
-
@daddygames I'm detecting it by `AppLifecycleState.inactive`. It works on iOS, but doesn't work on Android. Do you have a better way of detecting? – jakub Oct 15 '21 at 15:25
-
I cannot attest to the capabilities available here. This post might be helpful for covering both Android and iOS => [How do I check if the Flutter application is in the foreground or not?](https://stackoverflow.com/a/52890987/3224608) There is always the option to do this in the native code of each platform as well. – daddygames Oct 15 '21 at 17:46
-
Exactly, that’s how I’m checking it. I guess, the problem on Android is that it triggers inactive too late and is not able to override it on time – jakub Oct 16 '21 at 08:07
-
I've described here the exact problem https://stackoverflow.com/questions/69594245/why-in-applifecyclestate-inactive-state-widgets-are-not-redrawn-every-time – jakub Oct 16 '21 at 09:22
1 Answers
4
I was looking for doing the same and here is the solution I've implemented.
I used the Overlay widget to add the blur effect and use the AppLifecycleState to show it or not. Look at the code snippet below. (and thanks to this post for the background blur effect code snippet)
You can find working demo here
MaterialApp(
...,
builder: (BuildContext builderContext, Widget? child) => Overlay(
initialEntries: <OverlayEntry>[
OverlayEntry(
builder: (BuildContext context) => AppLifecycleOverlay(),
)
],
),
)
class AppLifecycleOverlay extends StatefulWidget {
const AppLifecycleOverlay({Key? key}) : super(key: key);
@override
State<AppLifecycleOverlay> createState() => _AppLifecycleOverlayState();
}
class _AppLifecycleOverlayState extends State<AppLifecycleOverlay>
with WidgetsBindingObserver {
bool shouldBlur = false;
@override
void initState() {
super.initState();
WidgetsBinding.instance?.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(() {
shouldBlur = state == AppLifecycleState.inactive ||
state == AppLifecycleState.paused;
});
}
@override
Widget build(BuildContext context) {
if (shouldBlur) {
return BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8, sigmaY: 8),
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
color: Colors.grey.shade200.withOpacity(0.5),
),
);
}
return Container();
}
}

Nicolas jacquet
- 41
- 3