diff --git a/packages/flutter/lib/src/cupertino/route.dart b/packages/flutter/lib/src/cupertino/route.dart index 390bac8b41..ae68440c21 100644 --- a/packages/flutter/lib/src/cupertino/route.dart +++ b/packages/flutter/lib/src/cupertino/route.dart @@ -175,6 +175,12 @@ mixin CupertinoRouteTransitionMixin on PageRoute { ((nextRoute is CupertinoRouteTransitionMixin) || nextRouteHasDelegatedTransition); } + @override + bool canTransitionFrom(TransitionRoute previousRoute) { + // Supress previous route from transitioning if this is a fullscreenDialog route. + return previousRoute is PageRoute && !fullscreenDialog; + } + @override Widget buildPage(BuildContext context, Animation animation, Animation secondaryAnimation) { final Widget child = buildContent(context); diff --git a/packages/flutter/lib/src/material/page.dart b/packages/flutter/lib/src/material/page.dart index 2b87aaa978..5a5fe8122b 100644 --- a/packages/flutter/lib/src/material/page.dart +++ b/packages/flutter/lib/src/material/page.dart @@ -124,6 +124,12 @@ mixin MaterialRouteTransitionMixin on PageRoute { ((nextRoute is MaterialRouteTransitionMixin) || nextRouteHasDelegatedTransition); } + @override + bool canTransitionFrom(TransitionRoute previousRoute) { + // Supress previous route from transitioning if this is a fullscreenDialog route. + return previousRoute is PageRoute && !fullscreenDialog; + } + @override Widget buildPage( BuildContext context, diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart index 182bf0b70d..fa71528806 100644 --- a/packages/flutter/test/cupertino/route_test.dart +++ b/packages/flutter/test/cupertino/route_test.dart @@ -2691,6 +2691,54 @@ void main() { await tester.pumpAndSettle(); }); + testWidgets('fullscreen routes do not transition previous route', (WidgetTester tester) async { + await tester.pumpWidget( + CupertinoApp( + initialRoute: '/', + onGenerateRoute: (RouteSettings settings) { + if (settings.name == '/') { + return PageRouteBuilder( + pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar( + middle: Text('Page 1'), + ), + child: Container() + ); + }, + ); + } + return CupertinoPageRoute( + builder: (BuildContext context) { + return CupertinoPageScaffold( + navigationBar: const CupertinoNavigationBar( + middle: Text('Page 2'), + ), + child: Container(), + ); + }, + fullscreenDialog: true, + ); + }, + ), + ); + + expect(find.text('Page 1'), findsOneWidget); + expect(find.text('Page 2'), findsNothing); + + final double pageTitleDX = tester.getTopLeft(find.text('Page 1')).dx; + + tester.state(find.byType(Navigator)).pushNamed('/next'); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 100)); + + // Second page transition has started. + expect(find.text('Page 2'), findsOneWidget); + + // First page has not moved. + expect(tester.getTopLeft(find.text('Page 1')).dx, equals(pageTitleDX)); + }); + testWidgets('Setting CupertinoDialogRoute.requestFocus to false does not request focus on the dialog', (WidgetTester tester) async { late BuildContext savedContext; final FocusNode focusNode = FocusNode(); diff --git a/packages/flutter/test/material/page_test.dart b/packages/flutter/test/material/page_test.dart index 7ae339e8e2..26c3cfefac 100644 --- a/packages/flutter/test/material/page_test.dart +++ b/packages/flutter/test/material/page_test.dart @@ -656,6 +656,54 @@ void main() { expect(tester.getTopLeft(find.text('Page 2')), Offset.zero); }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); + testWidgets('test fullscreen routes do not transition previous route', (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + initialRoute: '/', + onGenerateRoute: (RouteSettings settings) { + if (settings.name == '/') { + return PageRouteBuilder( + pageBuilder: (BuildContext context, Animation animation, Animation secondaryAnimation) { + return Scaffold( + appBar: AppBar( + title: const Text('Page 1'), + ), + body: Container() + ); + }, + ); + } + return MaterialPageRoute( + builder: (BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Page 2'), + ), + body: Container(), + ); + }, + fullscreenDialog: true, + ); + }, + ), + ); + + expect(find.text('Page 1'), findsOneWidget); + expect(find.text('Page 2'), findsNothing); + + final double pageTitleDX = tester.getTopLeft(find.text('Page 1')).dx; + + tester.state(find.byType(Navigator)).pushNamed('/next'); + await tester.pump(); + await tester.pump(const Duration(milliseconds: 100)); + + // Second page transition has started. + expect(find.text('Page 2'), findsOneWidget); + + // First page has not moved. + expect(tester.getTopLeft(find.text('Page 1')).dx, equals(pageTitleDX)); + }, variant: const TargetPlatformVariant({ TargetPlatform.iOS, TargetPlatform.macOS })); + testWidgets('test adaptable transitions switch during execution', (WidgetTester tester) async { await tester.pumpWidget( MaterialApp(