Skip to content

Instantly share code, notes, and snippets.

@schultek
Last active March 26, 2024 15:24
Show Gist options
  • Save schultek/cc2acd8014be255c2a639a98d47be4e0 to your computer and use it in GitHub Desktop.
Save schultek/cc2acd8014be255c2a639a98d47be4e0 to your computer and use it in GitHub Desktop.
An improved WillPopScope widget to allow for nested navigators. See https://github.com/flutter/flutter/issues/47088
import 'package:flutter/material.dart';
class NestedWillPopScope extends StatefulWidget {
const NestedWillPopScope({
Key? key,
required this.child,
required this.onWillPop,
}) : super(key: key);
final Widget child;
final WillPopCallback onWillPop;
@override
_NestedWillPopScopeState createState() => _NestedWillPopScopeState();
static _NestedWillPopScopeState? of(BuildContext context) {
return context.findAncestorStateOfType<_NestedWillPopScopeState>();
}
}
class _NestedWillPopScopeState extends State<NestedWillPopScope> {
ModalRoute<dynamic>? _route;
_NestedWillPopScopeState? _descendant;
_NestedWillPopScopeState? get descendant => _descendant;
set descendant(_NestedWillPopScopeState? state) {
_descendant = state;
updateRouteCallback();
}
Future<bool> onWillPop() async {
bool? willPop;
if (_descendant != null) {
willPop = await _descendant!.onWillPop();
}
if (willPop == null || willPop) {
willPop = await widget.onWillPop();
}
return willPop;
}
void updateRouteCallback() {
_route?.removeScopedWillPopCallback(onWillPop);
_route = ModalRoute.of(context);
_route?.addScopedWillPopCallback(onWillPop);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
var parentGuard = NestedWillPopScope.of(context);
if (parentGuard != null) {
parentGuard.descendant = this;
}
updateRouteCallback();
}
@override
void dispose() {
_route?.removeScopedWillPopCallback(onWillPop);
super.dispose();
}
@override
Widget build(BuildContext context) => widget.child;
}
@schultek
Copy link
Author

@m-azyoksul Here you go.

@bonkerman
Copy link

bonkerman commented Oct 18, 2022

Thanks a lot for this. However this is not complete and can cause errors. You should set the descendant of the parent to null on disposing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment