From 567d0045bf61965ba8f428c9a4a338d1787719d0 Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Mon, 21 Nov 2022 11:21:17 -0800 Subject: [PATCH] Add clip option for navigator (#115775) --- .../flutter/lib/src/widgets/navigator.dart | 12 ++++++- .../flutter/test/widgets/navigator_test.dart | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/widgets/navigator.dart b/packages/flutter/lib/src/widgets/navigator.dart index a00de26a2557..3d0979f313e8 100644 --- a/packages/flutter/lib/src/widgets/navigator.dart +++ b/packages/flutter/lib/src/widgets/navigator.dart @@ -1385,7 +1385,7 @@ class Navigator extends StatefulWidget { /// Creates a widget that maintains a stack-based history of child widgets. /// /// The [onGenerateRoute], [pages], [onGenerateInitialRoutes], - /// [transitionDelegate], [observers] arguments must not be null. + /// [transitionDelegate], [observers] arguments must not be null. /// /// If the [pages] is not empty, the [onPopPage] must not be null. const Navigator({ @@ -1398,6 +1398,7 @@ class Navigator extends StatefulWidget { this.onUnknownRoute, this.transitionDelegate = const DefaultTransitionDelegate(), this.reportsRouteUpdateToEngine = false, + this.clipBehavior = Clip.hardEdge, this.observers = const [], this.requestFocus = true, this.restorationScopeId, @@ -1563,6 +1564,14 @@ class Navigator extends StatefulWidget { /// Defaults to false. final bool reportsRouteUpdateToEngine; + /// {@macro flutter.material.Material.clipBehavior} + /// + /// In cases where clipping is not desired, consider setting this property to + /// [Clip.none]. + /// + /// Defaults to [Clip.hardEdge], and must not be null. + final Clip clipBehavior; + /// Whether or not the navigator and it's new topmost route should request focus /// when the new route is pushed onto the navigator. /// @@ -5253,6 +5262,7 @@ class NavigatorState extends State with TickerProviderStateMixin, Res bucket: bucket, child: Overlay( key: _overlayKey, + clipBehavior: widget.clipBehavior, initialEntries: overlay == null ? _allRouteOverlayEntries.toList(growable: false) : const [], ), ), diff --git a/packages/flutter/test/widgets/navigator_test.dart b/packages/flutter/test/widgets/navigator_test.dart index 9607888cd7ec..fc51821090bb 100644 --- a/packages/flutter/test/widgets/navigator_test.dart +++ b/packages/flutter/test/widgets/navigator_test.dart @@ -200,6 +200,39 @@ void main() { expect(find.text('home'), findsOneWidget); }); + testWidgets('Navigator can set clip behavior', (WidgetTester tester) async { + const MaterialPage page = MaterialPage(child: Text('page')); + await tester.pumpWidget( + MediaQuery( + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), + child: Directionality( + textDirection: TextDirection.ltr, + child: Navigator( + pages: const >[page], + onPopPage: (_, __) => false, + ), + ), + ), + ); + // Default to hard edge. + expect(tester.widget(find.byType(Overlay)).clipBehavior, Clip.hardEdge); + + await tester.pumpWidget( + MediaQuery( + data: MediaQueryData.fromWindow(WidgetsBinding.instance.window), + child: Directionality( + textDirection: TextDirection.ltr, + child: Navigator( + pages: const >[page], + clipBehavior: Clip.none, + onPopPage: (_, __) => false, + ), + ), + ), + ); + expect(tester.widget(find.byType(Overlay)).clipBehavior, Clip.none); + }); + testWidgets('Zero transition page-based route correctly notifies observers when it is popped', (WidgetTester tester) async { final List> pages = >[ const ZeroTransitionPage(name: 'Page 1'),