Open petrnymsa opened 3 years ago
Any new? How can i use nested navigation?
I have a solution.
The problem is that WillPopScope()
only adds callback to the current route. For nested navigation, it should be added to the navigator's MaterialWithModalsPageRoute
or CupertinoWithModalsPageRoute
instead. To do so, I wrote a custom ModalWillPopScope
widget:
import 'package:flutter/widgets.dart';
import 'package:modal_bottom_sheet/modal_bottom_sheet.dart';
///
/// This class is same as WillPopScope except we use getModalRoute() for getting the modal route
///
class ModalWillPopScope extends StatefulWidget {
const ModalWillPopScope({
Key? key,
required this.child,
required this.onWillPop,
}) : assert(child != null),
super(key: key);
final Widget child;
final WillPopCallback? onWillPop;
@override
State<ModalWillPopScope> createState() => _ModalWillPopScopeState();
}
class _ModalWillPopScopeState extends State<ModalWillPopScope> {
ModalRoute<dynamic>? _route;
ModalRoute<dynamic>? getModalRoute() {
final route = ModalRoute.of(context);
final navigator = Navigator.of(context);
final navigatorRoute = ModalRoute.of(navigator.context);
if (route is CupertinoModalBottomSheetRoute ||
route is MaterialWithModalsPageRoute) {
return route;
}
if (navigatorRoute is CupertinoModalBottomSheetRoute ||
navigatorRoute is MaterialWithModalsPageRoute) {
return navigatorRoute;
}
return null;
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (widget.onWillPop != null)
_route?.removeScopedWillPopCallback(widget.onWillPop!);
_route = getModalRoute();
if (widget.onWillPop != null)
_route?.addScopedWillPopCallback(widget.onWillPop!);
}
@override
void didUpdateWidget(ModalWillPopScope oldWidget) {
super.didUpdateWidget(oldWidget);
assert(_route == getModalRoute());
if (widget.onWillPop != oldWidget.onWillPop && _route != null) {
if (oldWidget.onWillPop != null)
_route!.removeScopedWillPopCallback(oldWidget.onWillPop!);
if (widget.onWillPop != null)
_route!.addScopedWillPopCallback(widget.onWillPop!);
}
}
@override
void dispose() {
if (widget.onWillPop != null)
_route?.removeScopedWillPopCallback(widget.onWillPop!);
super.dispose();
}
@override
Widget build(BuildContext context) => widget.child;
}
Then we can use it like this:
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: onWillPop,
child: ModalWillPopScope(
onWillPop: onWillPop,
child: ...,
),
);
}
@DaleLaw Could you provide a complete example of your solution or elaborate a little bit more. What widgets do I need to wrap and what would "onWillPop" look like? Appreciate!
In case we have nested navigation within modal and user drags modal to bottom we expect that modal should be closed.
In current implementation, it will correctly call WillPopScope (if any) but in case of nested navigation it only goes back one nested page.
Is there anything what we can change / set to have this behavior 1: If user swipe back, / press navigation back -> nested navigator goes back one page