予測型「戻る」ジェスチャーのサポートを追加する

図 1. スマートフォンでの予測型「戻る」ジェスチャーのデザインを示すモックアップ

予測型「戻る」は、ジェスチャー ナビゲーション機能で、ユーザーは「戻る」スワイプによって移動する先をプレビューできます。

たとえば図 1 のモックアップに示すように、「戻る」ジェスチャーによって、アプリの背後にあるホーム画面のアニメーション プレビューを表示できます。

Android 15 以降では、予測型「戻る」アニメーションの開発者向けオプションは使用できなくなりました。予測型「戻る」ジェスチャーを全体またはアクティビティ レベルで有効にしているアプリでは、ホームに戻る、タスク間、アクティビティ間のシステム アニメーションが表示されるようになりました。

このホームに戻るアニメーションをテストできます(このページの次のセクションで説明します)。

予測型「戻る」ジェスチャーをサポートするには、下位互換性がある OnBackPressedCallback AppCompat 1.6.0-alpha05(AndroidX)以上の API、または新しい OnBackInvokedCallback プラットフォーム API を使用して、アプリを更新する必要があります。ほとんどのアプリでは、下位互換性のある AndroidX API を使用します。

この更新は、「戻る」ナビゲーションを正しくインターセプトするための移行パスを提供するもので、KeyEvent.KEYCODE_BACK からの「戻る」インターセプトや、onBackPressed メソッドを含むクラス(ActivityDialog など)を、新しいシステムの「戻る」API で置き換えるためのものです。

Codelab と Google I/O の動画

ドキュメントのこのページの内容に加えて、Codelab もお試しください。AndroidX のアクティビティ API を使用して予測型「戻る」ジェスチャーを処理する WebView の一般的なユースケース実装を参照できます。

AndroidX とプラットフォームの API を実装する例については、Google I/O の動画もご覧ください。

デフォルトの「戻る」ナビゲーションを使用するアプリを更新する

この機能をサポートするようにアプリを更新することは、アプリにカスタムの「戻る」動作が実装されていなければ簡単です(「戻る」動作はシステムで処理されます)。このガイドの説明に沿って、この機能を有効にします。

アプリでフラグメントや Navigation コンポーネントを使用している場合は、AndroidX Activity 1.6.0-alpha05 以降へのアップグレードも行ってください。

カスタムの「戻る」ナビゲーションを使用するアプリを更新する

アプリにカスタム「戻る」動作が実装されている場合は、AndroidX 使用の有無や「戻る」ナビゲーションの処理方法に応じて移行パスが異なります。

アプリで AndroidX を使用している アプリでの「戻る」ナビゲーションの処理方法 おすすめの移行パス(このページのリンク)
AndroidX API AndroidX の既存の「戻る」動作を移行する
サポートされていないプラットフォーム API サポート対象外の「戻る」ナビゲーション API を含む AndroidX アプリを AndroidX API に移行する
× サポートされていないプラットフォーム API(移行可能) サポート対象外の「戻る」ナビゲーション API を使用するアプリをプラットフォーム API に移行する
サポートされていないプラットフォーム API(移行不可) 必須機能になるまでオプトインを延期する

AndroidX の「戻る」ナビゲーションの実装を移行する

このユースケースが最も一般的なおすすめの方法です。これは、OnBackPressedDispatcher によってカスタム ジェスチャー ナビゲーションを処理する、新規と既存両方のアプリに当てはまります(適切な「戻る」ナビゲーションを提供するを参照)。

アプリがこのケースにあてはまる場合は、次の手順に沿って、予測型「戻る」ジェスチャーのサポートを追加してください。

  1. すでに OnBackPressedDispatcher API を使用している API(フラグメントや Navigation コンポーネントなど)が、予測型「戻る」ジェスチャーとシームレスに連携するように、AndroidX Activity 1.6.0-alpha05 にアップグレードします。

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  2. このページの説明に従って、予測型「戻る」ジェスチャーを有効にします

サポート対象外の「戻る」ナビゲーション API を含む AndroidX アプリを AndroidX API に移行する

アプリで AndroidX ライブラリを使用しながら、サポートされていない「戻る」ナビゲーション API を実装または参照している場合は、AndroidX API に移行して新しい動作をサポートする必要があります。

サポートされていない API を AndroidX API に移行する手順は次のとおりです。

  1. OnBackPressedCallback の実装を使用して、システムの「戻る」ナビゲーション処理ロジックを AndroidX の OnBackPressedDispatcher に移行します。詳細なガイダンスについては、適切な「戻る」ナビゲーションを提供するをご覧ください。

  2. 「戻る」ジェスチャーのインターセプトを停止する準備ができたら、OnBackPressedCallback を無効にします。

  3. OnBackPressed または KeyEvent.KEYCODE_BACK による「戻る」イベントのインターセプトを停止します。

  4. 必ず AndroidX Activity 1.6.0-alpha05 にアップグレードしてください。

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  5. アプリを正常に移行したら、このページで説明しているように、予測型「戻る」ジェスチャーをオプトインして、ホームに戻るシステム アニメーションが表示されるようにします。

サポート対象外の「戻る」ナビゲーション API を使用するアプリをプラットフォーム API に移行する

アプリで AndroidX ライブラリを使用できず、サポートされていない API を使用してカスタム「戻る」ナビゲーションを実装または参照している場合は、OnBackInvokedCallback プラットフォーム API に移行する必要があります。

サポートされていない API をプラットフォーム API に移行するには、次の手順を行います。

  1. Android 13 以上を搭載したデバイスでは新しい OnBackInvokedCallback API を使用し、Android 12 以下を搭載したデバイスではサポートされていない API を使用します。

  2. OnBackInvokedCallback のカスタム「戻る」ロジックを onBackInvokedDispatcher に登録します。それによって現在のアクティビティが終了しなくなり、ユーザーがシステムの「戻る」ナビゲーションを完了した時点で、コールバックが「戻る」アクションに反応できるようになります。

  3. 「戻る」ジェスチャーのインターセプトを停止する準備ができたら、OnBackInvokedCallback の登録を解除します。解除しないと、システムの「戻る」ナビゲーションの使用時に、ビュー間で動かなくなってユーザーがアプリを強制終了しなければならなくなるなど、望ましくない動作が発生することがあります。

    onBackPressed からロジックを移行する方法の例を次に示します。

    Kotlin

    @Override
    fun onCreate() {
        if (BuildCompat.isAtLeastT()) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(
                OnBackInvokedDispatcher.PRIORITY_DEFAULT
            ) {
                /**
                 * onBackPressed logic goes here. For instance:
                 * Prevents closing the app to go home screen when in the
                 * middle of entering data to a form
                 * or from accidentally leaving a fragment with a WebView in it
                 *
                 * Unregistering the callback to stop intercepting the back gesture:
                 * When the user transitions to the topmost screen (activity, fragment)
                 * in the BackStack, unregister the callback by using
                 * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
                 * (https://developer.android.com/reference/kotlin/android/window/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
                 */
            }
        }
    }
    

    Java

    @Override
    void onCreate() {
      if (BuildCompat.isAtLeastT()) {
        getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
            OnBackInvokedDispatcher.PRIORITY_DEFAULT,
            () -> {
              /**
               * onBackPressed logic goes here - For instance:
               * Prevents closing the app to go home screen when in the
               * middle of entering data to a form
               * or from accidentally leaving a fragment with a WebView in it
               *
               * Unregistering the callback to stop intercepting the back gesture:
               * When the user transitions to the topmost screen (activity, fragment)
               * in the BackStack, unregister the callback by using
               * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
               * (https://developer.android.com/reference/kotlin/android/view/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
               */
            }
        );
      }
    }
    
  4. Android 13 以降では、OnBackPressed または KeyEvent.KEYCODE_BACK による「戻る」イベントのインターセプトを停止します。

  5. アプリを正常に移行したら、このページで説明しているように、予測型「戻る」ジェスチャーをオプトインして、OnBackInvokedCallback が有効になるようにします。

OnBackInvokedCallbackPRIORITY_DEFAULT または PRIORITY_OVERLAY で登録できますが、同様の AndroidX の OnBackPressedCallback では使用できません。PRIORITY_OVERLAY でコールバックを登録すると便利な場合があります。

これは、onKeyPreIme() から移行するときに、コールバックが「IME を開く」ではなく「戻る」ジェスチャーを受け取る必要がある場合に適用されます。IME は開いている場合 PRIORITY_DEFAULT でコールバックを登録します。PRIORITY_OVERLAY でコールバックを登録し、OnBackInvokedDispatcher が「IME を開く」ではなく「戻る」ジェスチャーをコールバックにディスパッチするようにします。

予測型「戻る」ジェスチャーをオプトインする

実際のケースに基づいてアプリを更新する方法を決定したら、予測型「戻る」ジェスチャーのサポートをオプトインします。

オプトインするには、AndroidManifest.xml<application> タグ内で、android:enableOnBackInvokedCallback フラグを true に設定します。

<application
    ...
    android:enableOnBackInvokedCallback="true"
    ... >
...
</application>

値を指定しない場合は、デフォルトで false に設定され、以下の処理が行われます。

  • 予測型「戻る」ジェスチャーのシステム アニメーションが無効になります。
  • OnBackInvokedCallback は無視されますが、OnBackPressedCallback 呼び出しは引き続き機能します。

アクティビティ レベルでオプトインする

Android 14 以降では、android:enableOnBackInvokedCallback フラグを使用することで、アクティビティ レベルで予測型システム アニメーションを有効にできます。この動作により、大規模なマルチアクティビティ アプリを予測型「戻る」ジェスチャーに移行しやすくなります。Android 15 では、予測型「戻る」がデベロッパー オプションの背後に表示されなくなりました。アプリは、予測型「戻る」を完全に有効にするか、アクティビティ レベルで有効にできます。

次のコードは、enableOnBackInvokedCallback を使用して MainActivity からホームに戻るシステム アニメーションを有効にする例を示しています。

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

        <activity
            android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        </activity>
        <activity
            android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        </activity>
    </application>
</manifest>

上記の例では、".SecondActivity"android:enableOnBackInvokedCallback=true を設定すると、クロスアクティビティ システム アニメーションが有効になります。

android:enableOnBackInvokedCallback フラグを使用する場合は、次の点にご注意ください。

  • android:enableOnBackInvokedCallback=false と設定すると、タグを設定した場所に応じて、アクティビティ レベルまたはアプリレベルで予測型「戻る」アニメーションがオフになります。また、システムに対して、OnBackInvokedCallback プラットフォーム API の呼び出しを無視するよう指示します。ただし、OnBackPressedCallback には下位互換性があり、Android 13 より前でサポートされていない onBackPressed API が呼び出されるため、OnBackPressedCallback の呼び出しは引き続き実行されます。
  • アプリレベルで enableOnBackInvokedCallback フラグを設定すると、アプリ内のすべてのアクティビティのデフォルト値が設定されます。アクティビティごとにデフォルトをオーバーライドするには、上記のコード例に示すように、アクティビティ レベルでフラグを設定します。

コールバックに関するベスト プラクティス

サポートされているシステムの「戻る」コールバック(BackHandler(Compose の場合)、OnBackPressedCallback または OnBackInvokedCallback)の使用に関するベスト プラクティスは次のとおりです。

各コールバックを有効または無効にする UI 状態を特定する

UI 状態は、UI を表すプロパティです。この手順の概要に沿って行うことをおすすめします。

  1. 各コールバックを有効または無効にする UI 状態を特定します。

  2. 観測可能なデータホルダーの型StateFlow や Compose の状態など)を使用してその状態を定義し、状態が変化したときにコールバックを有効または無効にします。

アプリで以前に「戻る」ロジックを条件ステートメントと関連付けていた場合、「戻る」イベントがすでに発生した後で対応している可能性があります。新しいコールバックでは、このパターンを使用しないでください。可能であれば、コールバックを条件ステートメントの外側に移動して、代わりにコールバックを観測可能なデータホルダーの型に関連付けます。

UI ロジックにシステムの「戻る」コールバックを使用する

UI ロジックは UI の表示方法を決定します。システムの「戻る」コールバックを使用して、ポップアップの表示やアニメーションの実行などの UI ロジックを実行します。

アプリがシステムの「戻る」コールバックを有効にしている場合、予測型アニメーションは実行されず、「戻る」イベントを処理する必要があります。UI 以外のロジックを実行するためだけにコールバックを作成しないでください。

たとえば、ログを記録するためだけに「戻る」イベントをインターセプトしている場合は、代わりにアクティビティやフラグメントのライフサイクル内でログを記録してください。

  • アクティビティからアクティビティへのケース、またはフラグメントからアクティビティへのケースに関しては、アクティビティのライフサイクル内で onDestroy 内の isFinishingtrue である場合にログを記録します。
  • フラグメントからフラグメントへのケースに関しては、フラグメントのビュー ライフサイクル内で onDestroy 内の isRemoving が true の場合にログを記録します。または、FragmentManager.OnBackStackChangedListener 内で onBackStackChangeStarted メソッドまたは onBackStackChangeCommitted メソッドを使用してログを記録します。

Compose の場合、Compose のデスティネーションに関連付けられた ViewModelonCleared() コールバック内でログに記録します。これは、Compose のデスティネーションがバックスタックからポップされて破棄されたことを知るための最適なシグナルです。

役割が 1 つのみのコールバックを作成する

ディスパッチャには複数のコールバックを追加できます。コールバックはスタックに追加され、最後に追加された有効なコールバックが、「戻る」操作ごとに 1 つのコールバックで次の「戻る」操作を処理します。

コールバックに単一の責任がある場合、コールバックの有効状態を管理しやすくなります。例:

スタック内のコールバックの順序。
図 2. コールバック スタック図。

図 2 は、スタック内に複数のコールバックがあり、それぞれが 1 つの処理を担当している方法を示しています。コールバックは、スタック内の上位のコールバックが無効になっている場合にのみ実行されます。この例では、ユーザーがフォームにデータを入力すると「本当によろしいですか?」コールバックが有効になり、それ以外の場合は無効になります。ユーザーが戻るをスワイプしてフォームを終了すると、コールバックによって確認ダイアログが開きます。

他のコールバックには、予測型「戻る」をサポートするマテリアル コンポーネント、Progress API を使用した AndroidX 遷移、または別のカスタム コールバックを含めることができます。

childFragmentManager のコールバックは、上記のコールバックが無効で、この FragmentManager のバックスタックが空でない場合(childFragmentManager がフラグメント内にアタッチされている場合)に実行されます。この例では、この内部コールバックは無効になっています。

同様に、上記のコールバックが無効でスタックが空でない場合、supportFragmentManager の内部コールバックが実行されます。NavigationComponentFragmentManager に依存するため、この動作は、ナビゲーションに FragmentManager または NavigationComponent を使用する場合でも一貫しています。この例では、ユーザーがフォームにテキストを入力しなかったために「本当に削除しますか?」コールバックが無効になった場合に、このコールバックが実行されます。

最後に、super.onBackPressed() はシステムレベルのコールバックです。上記のコールバックが無効になっている場合は、再度実行されます。ホームに戻る、アクティビティ間、タスク間のシステム アニメーションをトリガーするには、supportFragmentManager の戻るスタックが空で、内部コールバックが無効になっている必要があります。

予測型「戻る」ジェスチャーのアニメーションをテストする

Android 13 または Android 14 を使用している場合は、図 1 に示すホームに戻るアニメーションをテストできます。

このアニメーションをテストする手順は次のとおりです。

  1. デバイスで、[設定] > [システム] > [開発者向けオプション] に移動します。

  2. [予測型「戻る」アニメーション] を選択します。

  3. 更新したアプリを起動し、「戻る」ジェスチャーを使用して実際の動作を確認します。