diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart index 8ecbaeca3b..d0f4768566 100644 --- a/packages/flutter/lib/src/cupertino/route.dart +++ b/packages/flutter/lib/src/cupertino/route.dart @@ -976,6 +976,7 @@ Future showCupertinoDialog({ @required BuildContext context, @required WidgetBuilder builder, bool useRootNavigator = true, + RouteSettings routeSettings, }) { assert(builder != null); assert(useRootNavigator != null); @@ -990,5 +991,6 @@ Future showCupertinoDialog({ }, transitionBuilder: _buildCupertinoDialogTransitions, useRootNavigator: useRootNavigator, + routeSettings: routeSettings, ); } diff --git a/packages/flutter/lib/src/material/about.dart b/packages/flutter/lib/src/material/about.dart index c794090206..f4a8291e0e 100644 --- a/packages/flutter/lib/src/material/about.dart +++ b/packages/flutter/lib/src/material/about.dart @@ -223,8 +223,8 @@ class AboutListTile extends StatelessWidget { /// The licenses shown on the [LicensePage] are those returned by the /// [LicenseRegistry] API, which can be used to add more licenses to the list. /// -/// The [context] and [useRootNavigator] arguments are passed to [showDialog], -/// the documentation for which discusses how it is used. +/// The [context], [useRootNavigator] and [routeSettings] arguments are passed to +/// [showDialog], the documentation for which discusses how it is used. void showAboutDialog({ @required BuildContext context, String applicationName, @@ -233,6 +233,7 @@ void showAboutDialog({ String applicationLegalese, List children, bool useRootNavigator = true, + RouteSettings routeSettings, }) { assert(context != null); assert(useRootNavigator != null); @@ -248,6 +249,7 @@ void showAboutDialog({ children: children, ); }, + routeSettings: routeSettings, ); } diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index 9c63ae25b9..22e81baa8e 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -1086,8 +1086,8 @@ typedef SelectableDayPredicate = bool Function(DateTime day); /// provided by [Directionality]. If both [locale] and [textDirection] are not /// null, [textDirection] overrides the direction chosen for the [locale]. /// -/// The [context] and [useRootNavigator] arguments are passed to [showDialog], -/// the documentation for which discusses how it is used. +/// The [context], [useRootNavigator] and [routeSettings] arguments are passed to +/// [showDialog], the documentation for which discusses how it is used. /// /// The [builder] parameter can be used to wrap the dialog widget /// to add inherited widgets like [Theme]. @@ -1137,6 +1137,7 @@ Future showDatePicker({ TextDirection textDirection, TransitionBuilder builder, bool useRootNavigator = true, + RouteSettings routeSettings, }) async { assert(initialDate != null); assert(firstDate != null); @@ -1182,5 +1183,6 @@ Future showDatePicker({ builder: (BuildContext context) { return builder == null ? child : builder(context, child); }, + routeSettings: routeSettings, ); } diff --git a/packages/flutter/lib/src/material/dialog.dart b/packages/flutter/lib/src/material/dialog.dart index 4c3ecc5d2d..340a1d6561 100644 --- a/packages/flutter/lib/src/material/dialog.dart +++ b/packages/flutter/lib/src/material/dialog.dart @@ -872,6 +872,9 @@ Widget _buildMaterialDialogTransitions(BuildContext context, Animation a /// By default, `useRootNavigator` is `true` and the dialog route created by /// this method is pushed to the root navigator. /// +/// The `routeSettings` argument is passed to [showGeneralDialog], +/// see [RouteSettings] for details. +/// /// If the application has multiple [Navigator] objects, it may be necessary to /// call `Navigator.of(context, rootNavigator: true).pop(result)` to close the /// dialog rather than just `Navigator.pop(context, result)`. @@ -900,6 +903,7 @@ Future showDialog({ Widget child, WidgetBuilder builder, bool useRootNavigator = true, + RouteSettings routeSettings, }) { assert(child == null || builder == null); assert(useRootNavigator != null); @@ -926,5 +930,6 @@ Future showDialog({ transitionDuration: const Duration(milliseconds: 150), transitionBuilder: _buildMaterialDialogTransitions, useRootNavigator: useRootNavigator, + routeSettings: routeSettings, ); } diff --git a/packages/flutter/lib/src/material/time_picker.dart b/packages/flutter/lib/src/material/time_picker.dart index f41ebc0479..42e36a5cea 100644 --- a/packages/flutter/lib/src/material/time_picker.dart +++ b/packages/flutter/lib/src/material/time_picker.dart @@ -1749,8 +1749,8 @@ class _TimePickerDialogState extends State<_TimePickerDialog> { /// ``` /// {@end-tool} /// -/// The [context] and [useRootNavigator] arguments are passed to [showDialog], -/// the documentation for which discusses how it is used. +/// The [context], [useRootNavigator] and [routeSettings] arguments are passed to +/// [showDialog], the documentation for which discusses how it is used. /// /// The [builder] parameter can be used to wrap the dialog widget /// to add inherited widgets like [Localizations.override], @@ -1799,6 +1799,7 @@ Future showTimePicker({ @required TimeOfDay initialTime, TransitionBuilder builder, bool useRootNavigator = true, + RouteSettings routeSettings, }) async { assert(context != null); assert(initialTime != null); @@ -1812,6 +1813,7 @@ Future showTimePicker({ builder: (BuildContext context) { return builder == null ? dialog : builder(context, dialog); }, + routeSettings: routeSettings, ); } diff --git a/packages/flutter/lib/src/widgets/routes.dart b/packages/flutter/lib/src/widgets/routes.dart index 2ea1dd2f2e..f0ee871815 100644 --- a/packages/flutter/lib/src/widgets/routes.dart +++ b/packages/flutter/lib/src/widgets/routes.dart @@ -1727,6 +1727,9 @@ class _DialogRoute extends PopupRoute { /// and leaves off the screen. By default, the transition is a linear fade of /// the page's contents. /// +/// The `routeSettings` will be used in the construction of the dialog's route. +/// See [RouteSettings] for more details. +/// /// Returns a [Future] that resolves to the value (if any) that was passed to /// [Navigator.pop] when the dialog was closed. /// @@ -1743,6 +1746,7 @@ Future showGeneralDialog({ Duration transitionDuration, RouteTransitionsBuilder transitionBuilder, bool useRootNavigator = true, + RouteSettings routeSettings, }) { assert(pageBuilder != null); assert(useRootNavigator != null); @@ -1754,6 +1758,7 @@ Future showGeneralDialog({ barrierColor: barrierColor, transitionDuration: transitionDuration, transitionBuilder: transitionBuilder, + settings: routeSettings, )); } diff --git a/packages/flutter/test/material/dialog_test.dart b/packages/flutter/test/material/dialog_test.dart index 79f606e578..2bd1161831 100644 --- a/packages/flutter/test/material/dialog_test.dart +++ b/packages/flutter/test/material/dialog_test.dart @@ -1170,6 +1170,60 @@ void main() { expect(content.localToGlobal(Offset.zero), equals(contentOriginalOffset)); }); }); + + testWidgets('Dialog with RouteSettings', (WidgetTester tester) async { + RouteSettings currentRouteSetting; + + await tester.pumpWidget( + MaterialApp( + navigatorObservers: [ + _ClosureNavigatorObserver(onDidChange: (Route newRoute) { + currentRouteSetting = newRoute?.settings; + }) + ], + home: const Material( + child: Center( + child: RaisedButton( + onPressed: null, + child: Text('Go'), + ), + ), + ), + ), + ); + + final BuildContext context = tester.element(find.text('Go')); + const RouteSettings exampleSetting = RouteSettings(name: 'simple'); + + final Future result = showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + title: const Text('Title'), + children: [ + SimpleDialogOption( + child: const Text('X'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + routeSettings: exampleSetting, + ); + + await tester.pumpAndSettle(); + expect(find.text('Title'), findsOneWidget); + expect(currentRouteSetting, exampleSetting); + + await tester.tap(find.text('X')); + await tester.pumpAndSettle(); + + expect(await result, isNull); + await tester.pumpAndSettle(); + expect(currentRouteSetting?.name, '/'); + }); } class DialogObserver extends NavigatorObserver { @@ -1183,3 +1237,21 @@ class DialogObserver extends NavigatorObserver { super.didPush(route, previousRoute); } } + +class _ClosureNavigatorObserver extends NavigatorObserver { + _ClosureNavigatorObserver({@required this.onDidChange}); + + final void Function(Route newRoute) onDidChange; + + @override + void didPush(Route route, Route previousRoute) => onDidChange(route); + + @override + void didPop(Route route, Route previousRoute) => onDidChange(previousRoute); + + @override + void didRemove(Route route, Route previousRoute) => onDidChange(previousRoute); + + @override + void didReplace({Route newRoute, Route oldRoute}) => onDidChange(newRoute); +}