diff --git a/README.md b/README.md index d2162614..37505f51 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,19 @@ If you are pushing a new `modal` screen, use the following function: - To push bottom sheet on top of the Navigation Bar, use showModalBottomScreen and set it's property `useRootNavigator` to true. See example project for an illustration. +- To handle PopScopes down in the widget tree just implement 'NestedWillPopScope': + + ```dart + import 'package:persistent_bottom_nav_bar/models/nested_will_pop_scope.dart'; + + NestedWillPopScope( + onWillPop: () async { + 'your statements to handle PopScope' + }, + child: ThirdNestedScreen(), + ); + ``` + ## Custom Navigation Bar Styling If you want to have your own style for the navigation bar, follow these steps: diff --git a/example/pubspec.lock b/example/pubspec.lock index 9e9ce622..3d459c07 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" boolean_selector: dependency: transitive description: @@ -99,7 +99,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -134,7 +134,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" typed_data: dependency: transitive description: diff --git a/lib/models/nested_will_pop_scope.dart b/lib/models/nested_will_pop_scope.dart new file mode 100644 index 00000000..07d8d2e5 --- /dev/null +++ b/lib/models/nested_will_pop_scope.dart @@ -0,0 +1,67 @@ +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 { + ModalRoute? _route; + + _NestedWillPopScopeState? _descendant; + + //ignore: avoid_setters_without_getters + set descendant(_NestedWillPopScopeState state) { + _descendant = state; + updateRouteCallback(); + } + + Future 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(); + final 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; +} diff --git a/lib/persistent-tab-view.dart b/lib/persistent-tab-view.dart index 559cfd88..8be3a61e 100644 --- a/lib/persistent-tab-view.dart +++ b/lib/persistent-tab-view.dart @@ -6,6 +6,8 @@ import 'dart:ui'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/cupertino.dart' show CupertinoApp; +import 'models/nested_will_pop_scope.dart'; + //Main TabView Widget part 'persistent-tab-view.widget.dart'; diff --git a/lib/persistent-tab-view.widget.dart b/lib/persistent-tab-view.widget.dart index 9b359c62..6c34c912 100644 --- a/lib/persistent-tab-view.widget.dart +++ b/lib/persistent-tab-view.widget.dart @@ -667,11 +667,11 @@ class _PersistentTabViewState extends State { } if (widget.handleAndroidBackButtonPress || widget.onWillPop != null) { - return WillPopScope( + return NestedWillPopScope( onWillPop: !widget.handleAndroidBackButtonPress && widget.onWillPop != null ? widget.onWillPop!(_contextList[_controller!.index]) - as Future Function()? + as Future Function() : widget.handleAndroidBackButtonPress && widget.onWillPop != null ? () async { if (_controller!.index == 0 && diff --git a/pubspec.lock b/pubspec.lock index 49a0ce66..ad6d1df4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,7 +7,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.5.0" + version: "2.6.1" boolean_selector: dependency: transitive description: @@ -92,7 +92,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.8.1" stack_trace: dependency: transitive description: @@ -127,7 +127,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.19" + version: "0.3.0" typed_data: dependency: transitive description: