diff --git a/packages/flutter/lib/src/widgets/pages.dart b/packages/flutter/lib/src/widgets/pages.dart index 89bf3e74ff..12da358cad 100644 --- a/packages/flutter/lib/src/widgets/pages.dart +++ b/packages/flutter/lib/src/widgets/pages.dart @@ -62,6 +62,7 @@ class PageRouteBuilder extends PageRoute { @required this.pageBuilder, this.transitionsBuilder = _defaultTransitionsBuilder, this.transitionDuration = const Duration(milliseconds: 300), + this.reverseTransitionDuration = const Duration(milliseconds: 300), this.opaque = true, this.barrierDismissible = false, this.barrierColor, @@ -93,6 +94,9 @@ class PageRouteBuilder extends PageRoute { @override final Duration transitionDuration; + @override + final Duration reverseTransitionDuration; + @override final bool opaque; @@ -134,6 +138,7 @@ class TransitionBuilderPage extends Page { @required this.pageBuilder, this.transitionsBuilder = _defaultTransitionsBuilder, this.transitionDuration = const Duration(milliseconds: 300), + this.reverseTransitionDuration = const Duration(milliseconds: 300), this.opaque = true, this.barrierDismissible = false, this.barrierColor, @@ -160,6 +165,9 @@ class TransitionBuilderPage extends Page { /// {@macro flutter.widgets.transitionRoute.transitionDuration} final Duration transitionDuration; + /// {@macro flutter.widgets.transitionRoute.reverseTransitionDuration} + final Duration reverseTransitionDuration; + /// {@macro flutter.widgets.transitionRoute.opaque} final bool opaque; @@ -197,6 +205,9 @@ class _PageBasedPageRouteBuilder extends PageRoute{ @override Duration get transitionDuration => _page.transitionDuration; + @override + Duration get reverseTransitionDuration => _page.reverseTransitionDuration; + @override bool get opaque => _page.opaque; diff --git a/packages/flutter/test/widgets/routes_test.dart b/packages/flutter/test/widgets/routes_test.dart index 6d9f75e196..53a4787376 100644 --- a/packages/flutter/test/widgets/routes_test.dart +++ b/packages/flutter/test/widgets/routes_test.dart @@ -674,6 +674,109 @@ void main() { expect(find.text('second'), findsOneWidget); }); + group('PageRouteBuilder', () { + testWidgets('reverseTransitionDuration defaults to 300ms', (WidgetTester tester) async { + // Default PageRouteBuilder reverse transition duration should be 300ms. + await tester.pumpWidget( + MaterialApp( + onGenerateRoute: (RouteSettings settings) { + return MaterialPageRoute( + builder: (BuildContext context) { + return RaisedButton( + onPressed: () { + Navigator.of(context).push( + PageRouteBuilder( + settings: settings, + pageBuilder: (BuildContext context, Animation input, Animation out) { + return const Text('Page Two'); + }, + ) + ); + }, + child: const Text('Open page'), + ); + }, + ); + }, + ) + ); + + // Open the new route. + await tester.tap(find.byType(RaisedButton)); + await tester.pumpAndSettle(); + expect(find.text('Open page'), findsNothing); + expect(find.text('Page Two'), findsOneWidget); + + // Pop the new route. + tester.state(find.byType(Navigator)).pop(); + await tester.pump(); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') should be present halfway through the reverse transition. + await tester.pump(const Duration(milliseconds: 150)); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') should be present at the very end of the reverse transition. + await tester.pump(const Duration(milliseconds: 150)); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') have transitioned out after 300ms. + await tester.pump(const Duration(milliseconds: 1)); + expect(find.text('Page Two'), findsNothing); + expect(find.text('Open page'), findsOneWidget); + }); + + testWidgets('reverseTransitionDuration can be customized', (WidgetTester tester) async { + await tester.pumpWidget(MaterialApp( + onGenerateRoute: (RouteSettings settings) { + return MaterialPageRoute( + builder: (BuildContext context) { + return RaisedButton( + onPressed: () { + Navigator.of(context).push( + PageRouteBuilder( + settings: settings, + pageBuilder: (BuildContext context, Animation input, Animation out) { + return const Text('Page Two'); + }, + // modified value, default PageRouteBuilder reverse transition duration should be 300ms. + reverseTransitionDuration: const Duration(milliseconds: 150), + ) + ); + }, + child: const Text('Open page'), + ); + }, + ); + }) + ); + + // Open the new route. + await tester.tap(find.byType(RaisedButton)); + await tester.pumpAndSettle(); + expect(find.text('Open page'), findsNothing); + expect(find.text('Page Two'), findsOneWidget); + + // Pop the new route. + tester.state(find.byType(Navigator)).pop(); + await tester.pump(); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') should be present halfway through the reverse transition. + await tester.pump(const Duration(milliseconds: 75)); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') should be present at the very end of the reverse transition. + await tester.pump(const Duration(milliseconds: 75)); + expect(find.text('Page Two'), findsOneWidget); + + // Text('Page Two') have transitioned out after 500ms. + await tester.pump(const Duration(milliseconds: 1)); + expect(find.text('Page Two'), findsNothing); + expect(find.text('Open page'), findsOneWidget); + }); + }); + group('TransitionRoute', () { testWidgets('secondary animation is kDismissed when next route finishes pop', (WidgetTester tester) async { final GlobalKey navigator = GlobalKey();