Last active
March 26, 2024 15:24
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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