Movatterモバイル変換


[0]ホーム

URL:


Skip to main content

docs.flutter.dev uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.

Learn more

Flutter 3.41 is live! Check out theblog post!

The default page transition on Android is now PredictiveBackPageTransitionsBuilder

Android's default page transition has been updated to match the platform and to support predictive back.

Summary

#

The default page transition on Android has been updated fromZoomPageTransitionsBuilder toPredictiveBackPageTransitionsBuilder. When not using predictive back, this falls back toFadeForwardsPageTransitionsBuilder.

Context

#

Android has been rolling out a feature called predictive back, where performing a back gesture allows the user to peek at the previous route or app and possibly cancel the navigation. Flutter added support for this with thePopScope widget followed byPredictiveBackPageTransitionsBuilder.

In the meantime, Android also updated its default page transition. Flutter added support for this withFadeForwardsPageTransitionsBuilder.

Description of change

#

With this change,PredictiveBackPageTransitionsBuilder has replacedZoomPageTransitionsBuilder as the default page transition on Android. During a normal page transition without a predictive back gesture, users see the newFadeForwardsPageTransitionsBuilder as the default page transition. When using a predictive back gesture, the page animates along with the gesture and allows canceling or committing to the back navigation.

In this example, no page transition is explicitly given, so thedefault is set toPredictiveBackPageTransitionsBuilder in the theme on Android.

dart
MaterialApp(theme:ThemeData(brightness:Brightness.light,),home:constPageOne(),);

Migration guide

#

If you want to keep your app's page transition on the oldZoomPageTransitionsBuilder, you can simply set your page transition explicitly in your app's theme. Keep in mind that you will not be able to support predictive back route transitions.

Code before migration:

dart
returnMaterialApp(theme:ThemeData(brightness:Brightness.light,// pageTransitionsTheme is the default.),home:constMyFirstScreen(),);

Code after migration:

dart
MaterialApp(theme:ThemeData(// pageTransitionsTheme is explicitly set to the old transition on Android.pageTransitionsTheme:constPageTransitionsTheme(builders:{TargetPlatform.android:ZoomPageTransitionsBuilder(),},),),home:constMyFirstScreen(),);

One side effect of changing the default transition is that the duration that it takes to transition between pages has increased from 300ms to 450ms. This might cause breakages in tests that depend on the previous transition duration. Fortunately, it's possible to useTransitionDurationObserver to keep tests independent of whatever page transition is used.

Code before migration:

dart
testWidgets('example',(WidgetTestertester)async{awaittester.pumpWidget(MaterialApp(onGenerateRoute:(RouteSettingssettings){...},),);expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsNothing);// Pump through the whole transition, hardcoded to 300ms.awaittester.tap(find.text('Next'));awaittester.pump(constDuration(milliseconds:300));expect(find.text('Page 1'),findsNothing);expect(find.text('Page 2'),findsOneWidget);});

Code after migration:

dart
testWidgets('example',(WidgetTestertester)async{finalTransitionDurationObserverobserver=TransitionDurationObserver();awaittester.pumpWidget(MaterialApp(navigatorObservers:<NavigatorObserver>[observer],onGenerateRoute:(RouteSettingssettings){...},),);expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsNothing);// Pump through the whole transition independent of the duration.awaittester.tap(find.text('Next'));awaitobserver.pumpPastTransition(tester);expect(find.text('Page 1'),findsNothing);expect(find.text('Page 2'),findsOneWidget);});

It's even possible to write tests that need to pump part of the way through a page transition without depending on the exact duration.

Code before migration:

dart
testWidgets('example',(WidgetTestertester)async{awaittester.pumpWidget(MaterialApp(onGenerateRoute:(RouteSettingssettings){...},),);expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsNothing);// Pump through half of the transition with a hardcoded value.awaittester.tap(find.text('Back'));awaittester.pump(constDuration(milliseconds:150));expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsOneWidget);});

Code after migration:

dart
testWidgets('example',(WidgetTestertester)async{finalTransitionDurationObserverobserver=TransitionDurationObserver();awaittester.pumpWidget(MaterialApp(navigatorObservers:<NavigatorObserver>[observer],onGenerateRoute:(RouteSettingssettings){...},),);expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsNothing);// Pump through half of the transition independent of the duration.awaittester.tap(find.text('Back'));awaittester.pump(observer.transitionDuration~/2);expect(find.text('Page 1'),findsOneWidget);expect(find.text('Page 2'),findsOneWidget);});

Timeline

#

Landed in version: 3.37.0-0.0.pre
In stable release: 3.38.0

References

#

API documentation:

Relevant issues:

Relevant PRs:

Was this page's content helpful?

Unless stated otherwise, the documentation on this site reflects Flutter 3.41.2. Page last updated on 2025-11-12.View source orreport an issue.


[8]ページ先頭

©2009-2026 Movatter.jp