diff --git a/packages/animations/lib/src/open_container.dart b/packages/animations/lib/src/open_container.dart index c46bbea1828f..f436113f362e 100644 --- a/packages/animations/lib/src/open_container.dart +++ b/packages/animations/lib/src/open_container.dart @@ -72,6 +72,7 @@ class OpenContainer extends StatefulWidget { this.tappable = true, this.transitionDuration = const Duration(milliseconds: 300), this.transitionType = ContainerTransitionType.fade, + this.useRootNavigator = false, }) : assert(closedColor != null), assert(openColor != null), assert(closedElevation != null), @@ -82,6 +83,7 @@ class OpenContainer extends StatefulWidget { assert(openBuilder != null), assert(tappable != null), assert(transitionType != null), + assert(useRootNavigator != null), super(key: key); /// Background color of the container while it is closed. @@ -207,6 +209,14 @@ class OpenContainer extends StatefulWidget { /// Defaults to [ContainerTransitionType.fade]. final ContainerTransitionType transitionType; + /// The [useRootNavigator] argument is used to determine whether to push the + /// route for [openBuilder] to the Navigator furthest from or nearest to + /// the given context. + /// + /// By default, [useRootNavigator] is false and the route created will push + /// to the nearest navigator. + final bool useRootNavigator; + @override _OpenContainerState createState() => _OpenContainerState(); } @@ -224,8 +234,9 @@ class _OpenContainerState extends State { // same widget included in the [_OpenContainerRoute] where it fades out. final GlobalKey _closedBuilderKey = GlobalKey(); - Future openContainer() async { - await Navigator.of(context).push(_OpenContainerRoute( + Future openContainer() async { + await Navigator.of(context, rootNavigator: widget.useRootNavigator) + .push(_OpenContainerRoute( closedColor: widget.closedColor, openColor: widget.openColor, closedElevation: widget.closedElevation, diff --git a/packages/animations/test/open_container_test.dart b/packages/animations/test/open_container_test.dart index e3de40a4b5fe..74f9bdaffedc 100644 --- a/packages/animations/test/open_container_test.dart +++ b/packages/animations/test/open_container_test.dart @@ -1110,6 +1110,7 @@ void main() { ), ), )); + await tester.tap(find.text('Closed')); await tester.pumpAndSettle(); @@ -1448,6 +1449,7 @@ void main() { expect(find.text('Closed 2'), findsNothing); expect(find.text('Open 2'), findsOneWidget); }); + testWidgets('onClosed callback is called when container has closed', (WidgetTester tester) async { bool hasClosed = false; @@ -1490,6 +1492,80 @@ void main() { expect(find.text('Closed'), findsOneWidget); expect(hasClosed, isTrue); }); + + Widget _createRootNavigatorTest({ + @required Key appKey, + @required Key nestedNavigatorKey, + @required bool useRootNavigator, + }) { + return MaterialApp( + key: appKey, + // a nested navigator + home: Navigator( + key: nestedNavigatorKey, + onGenerateRoute: (RouteSettings route) { + return MaterialPageRoute( + settings: route, + builder: (BuildContext context) { + return Container( + child: OpenContainer( + useRootNavigator: useRootNavigator, + closedBuilder: (BuildContext context, _) { + return const Text('Closed'); + }, + openBuilder: (BuildContext context, _) { + return const Text('Opened'); + })); + }); + })); + } + + testWidgets( + 'Verify that "useRootNavigator: false" uses the correct navigator', + (WidgetTester tester) async { + const Key appKey = Key('App'); + const Key nestedNavigatorKey = Key('Nested Navigator'); + + await tester.pumpWidget(_createRootNavigatorTest( + appKey: appKey, + nestedNavigatorKey: nestedNavigatorKey, + useRootNavigator: false)); + + await tester.tap(find.text('Closed')); + await tester.pumpAndSettle(); + + expect( + find.descendant(of: find.byKey(appKey), matching: find.text('Opened')), + findsOneWidget); + + expect( + find.descendant( + of: find.byKey(nestedNavigatorKey), matching: find.text('Opened')), + findsOneWidget); + }); + + testWidgets('Verify that "useRootNavigator: true" uses the correct navigator', + (WidgetTester tester) async { + const Key appKey = Key('App'); + const Key nestedNavigatorKey = Key('Nested Navigator'); + + await tester.pumpWidget(_createRootNavigatorTest( + appKey: appKey, + nestedNavigatorKey: nestedNavigatorKey, + useRootNavigator: true)); + + await tester.tap(find.text('Closed')); + await tester.pumpAndSettle(); + + expect( + find.descendant(of: find.byKey(appKey), matching: find.text('Opened')), + findsOneWidget); + + expect( + find.descendant( + of: find.byKey(nestedNavigatorKey), matching: find.text('Opened')), + findsNothing); + }); } Color _getScrimColor(WidgetTester tester) {