diff --git a/packages/material_ui/lib/src/predictive_back_page_transitions_builder.dart b/packages/material_ui/lib/src/predictive_back_page_transitions_builder.dart index eb235c261963..67ee30be124c 100644 --- a/packages/material_ui/lib/src/predictive_back_page_transitions_builder.dart +++ b/packages/material_ui/lib/src/predictive_back_page_transitions_builder.dart @@ -76,11 +76,8 @@ class PredictiveBackPageTransitionsBuilder extends PageTransitionsBuilder { PredictiveBackEvent? startBackEvent, PredictiveBackEvent? currentBackEvent, ) { - // Only do a predictive back transition when the user is performing a - // pop gesture. Otherwise, for things like button presses or other - // programmatic navigation, fall back to - // FadeForwardsPageTransitionsBuilder. - if (route.popGestureInProgress) { + // Only use the predictive back transition during an active back gesture. + if (phase != _PredictiveBackPhase.idle) { return _PredictiveBackSharedElementPageTransition( isDelegatedTransition: true, animation: animation, @@ -156,10 +153,8 @@ class PredictiveBackFullscreenPageTransitionsBuilder extends PageTransitionsBuil PredictiveBackEvent? startBackEvent, PredictiveBackEvent? currentBackEvent, ) { - // Only do a predictive back transition when the user is performing a - // pop gesture. Otherwise, for things like button presses or other - // programmatic navigation, fall back to ZoomPageTransitionsBuilder. - if (route.popGestureInProgress) { + // Only use the predictive back transition during an active back gesture. + if (phase != _PredictiveBackPhase.idle) { return _PredictiveBackFullscreenPageTransition( animation: animation, secondaryAnimation: secondaryAnimation, diff --git a/packages/material_ui/pending_changelogs/change_2026_08_28_predictive_back_sheet_drag.yaml b/packages/material_ui/pending_changelogs/change_2026_08_28_predictive_back_sheet_drag.yaml new file mode 100644 index 000000000000..a2cc18f263b2 --- /dev/null +++ b/packages/material_ui/pending_changelogs/change_2026_08_28_predictive_back_sheet_drag.yaml @@ -0,0 +1,3 @@ +changelog: | + - Prevents a covered route from entering a predictive back transition while dragging a `CupertinoSheet`. +version: patch diff --git a/packages/material_ui/test/predictive_back_page_transitions_builder_test.dart b/packages/material_ui/test/predictive_back_page_transitions_builder_test.dart index 446a26e80e49..c8ff788ee73f 100644 --- a/packages/material_ui/test/predictive_back_page_transitions_builder_test.dart +++ b/packages/material_ui/test/predictive_back_page_transitions_builder_test.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:cupertino_ui/cupertino_ui.dart' show CupertinoPageScaffold, showCupertinoSheet; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -673,6 +674,70 @@ void main() { findsOneWidget, ); }); + + testWidgets( + 'route covered by a CupertinoSheet does not switch to the predictive back ' + 'transition while the sheet is dragged (${pageTransitionsBuilder.runtimeType})', + (WidgetTester tester) async { + await tester.pumpWidget( + MaterialApp( + theme: ThemeData( + pageTransitionsTheme: PageTransitionsTheme( + builders: { + for (final TargetPlatform platform in TargetPlatform.values) + platform: pageTransitionsBuilder, + }, + ), + ), + home: Builder( + builder: (BuildContext context) { + return Scaffold( + body: Center( + child: TextButton( + onPressed: () { + showCupertinoSheet( + context: context, + scrollableBuilder: (BuildContext context, ScrollController controller) { + return CupertinoPageScaffold( + child: ListView.builder( + controller: controller, + itemCount: 30, + itemBuilder: (BuildContext context, int index) { + return SizedBox(height: 56.0, child: Text('item $index')); + }, + ), + ); + }, + ); + }, + child: const Text('open sheet'), + ), + ), + ); + }, + ), + ), + ); + + await tester.tap(find.text('open sheet')); + await tester.pumpAndSettle(); + + expect(_findPredictiveBackPageTransition(pageTransitionsBuilder), findsNothing); + expect(_findFallbackPageTransition(pageTransitionsBuilder), findsOneWidget); + + final TestGesture gesture = await tester.startGesture(const Offset(100, 300)); + // A small drag first wins the gesture arena before the larger drag. + await gesture.moveBy(const Offset(0, 30)); + await gesture.moveBy(const Offset(0, 100)); + await tester.pump(); + + expect(_findPredictiveBackPageTransition(pageTransitionsBuilder), findsNothing); + expect(_findFallbackPageTransition(pageTransitionsBuilder), findsOneWidget); + + await gesture.up(); + await tester.pumpAndSettle(); + }, + ); } testWidgets('PredictiveBackPageTransitionsBuilder uses fallbackColor', (