diff --git a/sites/docs/src/content/add-to-app/android/add-flutter-fragment.md b/sites/docs/src/content/add-to-app/android/add-flutter-fragment.md index ae7e280b4fa..fc678bd6bea 100644 --- a/sites/docs/src/content/add-to-app/android/add-flutter-fragment.md +++ b/sites/docs/src/content/add-to-app/android/add-flutter-fragment.md @@ -278,8 +278,40 @@ The simplest integration path uses a new `FlutterEngine`, which comes with a non-trivial initialization time, leading to a blank UI until Flutter is initialized and rendered the first time. -Most of this time overhead can be avoided by using -a cached, pre-warmed `FlutterEngine`, which is discussed next. +Most of this time overhead can be avoided by using a cached, pre-warmed +`FlutterEngine`, which is discussed in +[Using a pre-warmed `FlutterEngine`](#using-a-pre-warmed-flutterengine). + +### Automatic back button and predictive back handling + +When embedding a `FlutterFragment` into a native Android app on Android 13 or +higher (API level 33+), you can configure the fragment to automatically handle +system back button presses and predictive back gestures without manually +forwarding `onBackPressed()`. + +Instead of overriding `onBackPressed` as shown above, set +`shouldAutomaticallyHandleOnBackPressed(true)` when building your fragment: + + + + +```kotlin +val flutterFragment = FlutterFragment.withNewEngine() + .shouldAutomaticallyHandleOnBackPressed(true) + .build() +``` + + + + +```java +FlutterFragment flutterFragment = FlutterFragment.withNewEngine() + .shouldAutomaticallyHandleOnBackPressed(true) + .build(); +``` + + + ## Using a pre-warmed `FlutterEngine` diff --git a/sites/docs/src/content/platform-integration/android/predictive-back.md b/sites/docs/src/content/platform-integration/android/predictive-back.md index 11766c4fc9b..fb7c7321cc6 100644 --- a/sites/docs/src/content/platform-integration/android/predictive-back.md +++ b/sites/docs/src/content/platform-integration/android/predictive-back.md @@ -2,60 +2,80 @@ title: Add the predictive-back gesture shortTitle: Predictive-back description: >- - Learn how to add the predictive back gesture to your Android app. + Learn how to enable and handle Android predictive back gestures in Flutter. --- -This feature has landed in Flutter, -but it's not enabled by default in Android itself yet. -You can try it out using the following instructions. +The Android predictive back gesture lets users preview +where a back gesture will navigate to, +whether that's the previous screen or the home screen, +before they commit to or cancel it. -## Configure your app +## Overview -Make sure your app supports Android API 33 or higher, -as predictive back won't work on older versions of Android. -Then, set the flag `android:enableOnBackInvokedCallback="true"` -in `android/app/src/main/AndroidManifest.xml`. +Starting with Android 14 (API level 34), predictive back animations are +enabled by default for system gestures when supported by the application. +Flutter provides built-in support for predictive back animations across +default page route transitions and custom pop handling. -## Configure your device +## Enable predictive back in Android -You need to enable Developer Mode and set a flag on your device, -so you can't yet expect predictive back to work on most users' -Android devices. If you want to try it out on your own device though, -make sure it's running API 33 or higher, and then in -**Settings => System => Developer** options, -make sure the switch is enabled next to **Predictive back animations**. +To support predictive back gestures in your Flutter app +on Android 13 or later: -## Set up your app +1. Open `android/app/src/main/AndroidManifest.xml`. +2. Add `android:enableOnBackInvokedCallback="true"` to the `` tag: -The predictive back route transitions are currently -not enabled by default, so for now you'll need to enable them -manually in your app. -Typically, you do this by setting them in your theme: - -```dart -MaterialApp( - theme: ThemeData( - pageTransitionsTheme: const PageTransitionsTheme( - builders: { - // Set the predictive back transitions for Android. - TargetPlatform.android: PredictiveBackPageTransitionsBuilder(), - }, - ), - ), - ... -), + + + + + ``` -## Run your app +## Handle back gestures with PopScope + +To customize back navigation or prevent users from accidentally leaving a +screen, use the [`PopScope`]({{site.api}}/flutter/widgets/PopScope-class.html) +widget. `PopScope` replaces the deprecated `WillPopScope` widget and +supports predictive back gestures. + +### Callback parameters -Lastly, just make sure you're using at least -Flutter version 3.22.2 to run your app, -which is the latest stable release at the time of this writing. +`PopScope` uses the `onPopInvokedWithResult` callback: -## For more information +* `didPop`: A boolean indicating whether the pop operation succeeded. + If `canPop` is `false`, `didPop` is `false`. +* `result`: An optional return payload passed when popping the route + (for example, with `Navigator.pop(context, result)`). + +### Example: Intercepting back navigation + +```dart +PopScope( + canPop: false, + onPopInvokedWithResult: (bool didPop, Object? result) async { + if (didPop) { + return; + } + final shouldLeave = await _showExitConfirmationDialog(context); + if (shouldLeave && context.mounted) { + Navigator.of(context).pop(result); + } + }, + child: Scaffold( + appBar: AppBar(title: const Text('Form Screen')), + body: const Center(child: Text('Complete the form before leaving.')), + ), +) +``` -You can find more information at the following link: +## More information -* [Android predictive back][] breaking change +For more details on API migrations, check out the +[Android predictive back migration guide]( +/release/breaking-changes/android-predictive-back). -[Android predictive back]: /release/breaking-changes/android-predictive-back diff --git a/sites/docs/src/content/release/breaking-changes/android-predictive-back.md b/sites/docs/src/content/release/breaking-changes/android-predictive-back.md index bad12548756..c2e41eff959 100644 --- a/sites/docs/src/content/release/breaking-changes/android-predictive-back.md +++ b/sites/docs/src/content/release/breaking-changes/android-predictive-back.md @@ -49,18 +49,18 @@ whether it was successful. The `PopScope` class directly replaces `WillPopScope` in order to enable predictive back. Instead of deciding whether a pop is possible at the time it occurs, this is set ahead of time with the `canPop` boolean. You can still -listen to pops by using `onPopInvoked`. +listen to pops by using `onPopInvokedWithResult`. ```dart PopScope( canPop: _myPopDisableEnableLogic(), - onPopInvoked: (bool didPop) { + onPopInvokedWithResult: (bool didPop, Object? result) { // Handle the pop. If `didPop` is false, it was blocked. }, ) ``` -### Form.canPop and Form.onPopInvoked +### Form.canPop and Form.onPopInvokedWithResult These two new parameters are based on `PopScope` and replace the deprecated `Form.onWillPop` parameter. They are used with `PopScope` in the same way as @@ -69,7 +69,7 @@ above. ```dart Form( canPop: _myPopDisableEnableLogic(), - onPopInvoked: (bool didPop) { + onPopInvokedWithResult: (bool didPop, Object? result) { // Handle the pop. If `didPop` is false, it was blocked. }, ) @@ -135,11 +135,11 @@ PopScope( ``` For cases where it's necessary to be notified that a -pop was attempted, the `onPopInvoked` method can be +pop was attempted, the `onPopInvokedWithResult` method can be used in a similar way to `onWillPop`. Keep in mind that while `onWillPop` was called before the pop was handled and had the ability to cancel it, -`onPopInvoked` is called after the pop is finished being handled. +`onPopInvokedWithResult` is called after the pop is finished being handled. Code before migration: @@ -158,7 +158,7 @@ Code after migration: ```dart PopScope( canPop: true, - onPopInvoked: (bool didPop) { + onPopInvokedWithResult: (bool didPop, Object? result) { _myHandleOnPopMethod(); }, child: ... @@ -197,12 +197,12 @@ NavigatorPopHandler( ) ``` -### Migrating from Form.onWillPop to Form.canPop and Form.onPopInvoked +### Migrating from Form.onWillPop to Form.canPop and Form.onPopInvokedWithResult Previously, `Form` used a `WillPopScope` instance under the hood and exposed its `onWillPop` method. This has been replaced with a `PopScope` that exposes its -`canPop` and `onPopInvoked` methods. +`canPop` and `onPopInvokedWithResult` methods. Migrating is identical to migrating from `WillPopScope` to `PopScope`, detailed above. @@ -326,7 +326,7 @@ Code after migration: ```dart return PopScope( canPop: false, - onPopInvoked: (bool didPop) async { + onPopInvokedWithResult: (bool didPop, Object? result) async { if (didPop) { return; } @@ -342,22 +342,9 @@ return PopScope( ### Supporting predictive back - 1. Run Android 14 (API level 34) or above. - 1. Enable the feature flag for predictive back on - the device under "Developer options". - This will be unnecessary on future versions of Android. - 1. Set `android:enableOnBackInvokedCallback="true"` in - `android/app/src/main/AndroidManifest.xml`. - If needed, refer to - [Android's full guide]({{site.android-dev}}/guide/navigation/custom-back/predictive-back-gesture). - for migrating Android apps to support predictive back. - 1. Make sure you're using version `3.14.0-7.0.pre` - of Flutter or greater. - 1. Make sure your Flutter app doesn't use the - `WillPopScope` widget. Using it disables - predictive back. If needed, use `PopScope` instead. - 1. Run the app and perform a back gesture (swipe from the - left side of the screen). +For complete setup instructions, guidelines on predictive back gesture +animations, and Android manifest configuration, check out how to [add the +predictive-back gesture](/platform-integration/android/predictive-back). ## Timeline @@ -372,7 +359,7 @@ API documentation: * [`NavigatorPopHandler`][] * [`PopEntry`][] * [`Form.canPop`][] -* [`Form.onPopInvoked`][] +* [`Form.onPopInvokedWithResult`][] * [`Route.popDisposition`][] * [`ModalRoute.registerPopEntry`][] * [`ModalRoute.unregisterPopEntry`][] @@ -390,7 +377,7 @@ Relevant PRs: [`NavigatorPopHandler`]: {{site.api}}/flutter/widgets/NavigatorPopHandler-class.html [`PopEntry`]: {{site.api}}/flutter/widgets/PopEntry-class.html [`Form.canPop`]: {{site.api}}/flutter/widgets/Form/canPop.html -[`Form.onPopInvoked`]: {{site.api}}/flutter/widgets/Form/onPopInvoked.html +[`Form.onPopInvokedWithResult`]: {{site.api}}/flutter/widgets/Form/onPopInvokedWithResult.html [`Route.popDisposition`]: {{site.api}}/flutter/widgets/Route/popDisposition.html [`ModalRoute.registerPopEntry`]: {{site.api}}/flutter/widgets/ModalRoute/registerPopEntry.html [`ModalRoute.unregisterPopEntry`]: {{site.api}}/flutter/widgets/ModalRoute/unregisterPopEntry.html diff --git a/sites/docs/src/content/ui/navigation/index.md b/sites/docs/src/content/ui/navigation/index.md index c71b5cf5ab7..340fb13af51 100644 --- a/sites/docs/src/content/ui/navigation/index.md +++ b/sites/docs/src/content/ui/navigation/index.md @@ -129,10 +129,16 @@ navigates by removing a _page-backed_ route from the Navigator, all _pageless_ routes after (up until the next _page-backed_ route) are removed too. :::note -You can't prevent navigation from page-backed screens using `WillPopScope`. +You can't prevent navigation from page-backed screens using `PopScope` +or the deprecated `WillPopScope`. Instead, you should consult your routing package's API documentation. + +For guidelines on migrating to `PopScope`, +check out the [Android predictive back migration guide][]. ::: +[Android predictive back migration guide]: /release/breaking-changes/android-predictive-back + ## Web support Apps using the `Router` class integrate with the browser History API to provide