予測型「戻る」アニメーションのサポートを追加する

システムの「戻る」API を使用する場合は、アプリ内アニメーションの受け取りをオプトインし、カスタム遷移をサポートすることができます。

動画: 予測型「戻る」アニメーション

オプトインすると、アプリは「ホームに戻る」、アクティビティ間、タスク間のアニメーションを表示します。

また、マテリアル コンポーネントの依存関係を MDC Android の v1.10.0 にアップグレードし、次のようなマテリアル コンポーネント アニメーションを受け取ることもできます。

詳しくは、GitHub のマテリアル コンポーネントのデベロッパー ガイダンスをご覧ください。

この動画では、Android 設定アプリを使用して、アクティビティ間と「ホームに戻る」の予測型「戻る」アニメーションの簡単な例を紹介します。

  1. アニメーションでは、ユーザーは後方にスワイプして前の設定画面に戻ります(アクティビティ間アニメーションの例)。
  2. 前の画面で、ユーザーが 2 回目のスワイプを始めると、ホーム画面のプレビューが壁紙とともに表示されます(「ホームに戻る」アニメーションの例)。
  3. ユーザーが右にスワイプし続けると、ウィンドウがホーム画面のアイコンまで縮小するアニメーションが表示されます。
  4. これで、ユーザーは完全にホーム画面に戻ります。

詳しくは、予測型「戻る」ジェスチャーのサポートを追加するをご覧ください。

カスタムのアプリ内遷移とアニメーションを追加する

カスタムのアプリ内プロパティ アニメーションと遷移、アクティビティ間のカスタム アニメーション、予測型「戻る」ジェスチャーを使用したカスタム フラグメント間のアニメーションを作成できます。

Progress API を使用してカスタム遷移を追加する

AndroidX Activity 1.8.0-alpha01 以降では、Predictive Back Progress API を使用して、アプリの予測型「戻る」ジェスチャーのカスタム アニメーションを開発できます。Progress API はビューのアニメーション化に役立ちますが、フラグメント間の遷移をアニメーション化する場合には制限があります。OnBackPressedCallbackhandleOnBackProgressed メソッド、handleOnBackCancelled メソッド、handleOnBackStarted メソッドを導入し、ユーザーが後方にスワイプしてオブジェクトをアニメーション化しました。システムから提供されるデフォルトのアニメーションやマテリアル コンポーネント アニメーション以上のものをカスタマイズする必要がある場合は、これらのメソッドを使用します。

ほとんどのアプリでは、下位互換性のある AndroidX API が使用されることが想定されますが、OnBackAnimationCallback インターフェース内には、Android 14 デベロッパー プレビュー 1 以降でテストできる同様のプラットフォーム API もあります。

AndroidX の遷移で Progress API を使用する

Android 14 以降では、AndroidX Transitions 1.5.0-alpha01 以降で Progress API を使用して、予測型「戻る」遷移を作成できます。

  1. ユーザーが後方にスワイプしたときに遷移を再生するには、beginDelayedTransition ではなく TransitionManager#controlDelayedTransition を使用します。
  2. handleOnBackStarted 内に遷移を作成します。
  3. currentFractionBackEvent.progress に関連付けることで、handleOnBackProgressed 内の「戻る」イベントで遷移を再生します。これにより、ユーザーが過去にスワイプした距離が開示されます。
  4. ユーザーが handleOnBackPressed で「戻る」操作を確定したら、遷移を終了します。
  5. 最後に、handleOnBackCancelled 内で遷移の状態をリセットします。

次の動画、Kotlin コード、XML は、OnBackPressedCallback で実装された 2 つのボックス間のカスタム遷移を示しています。

    class MyFragment : Fragment() {

    val transitionSet = TransitionSet().apply {
        addTransition(Fade(Fade.MODE_OUT))
        addTransition(ChangeBounds())
        addTransition(Fade(Fade.MODE_IN))
    }
    ...
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val callback = object : OnBackPressedCallback(enabled = false) {

            var controller: TransitionSeekController? = null

            @RequiresApi(34)
            override fun handleOnBackStarted(backEvent: BackEvent) {
                // Create the transition
                controller = TransitionManager.controlDelayedTransition(
                    binding.card,
                    transitionSet
                )
                changeTextVisibility(ShowText.SHORT)
            }

            @RequiresApi(34)
            override fun handleOnBackProgressed(backEvent: BackEvent) {
                // Play the transition as the user swipes back
                if (controller?.isReady == true) {
                    controller?.currentFraction = backEvent.progress
                }
            }

            override fun handleOnBackPressed() {
                // Finish playing the transition when the user commits back
                controller?.animateToEnd()
                this.isEnabled = false
            }

            @RequiresApi(34)
            override fun handleOnBackCancelled() {
                // If the user cancels the back gesture, reset the state
                transition(ShowText.LONG)
            }
        }

        binding.shortText.setOnClickListener {
            transition(ShowText.LONG)
            callback.isEnabled = true
        }

        this.requireActivity().onBackPressedDispatcher.addCallback(callback)
    }

    private fun transition(showText: ShowText) {
        TransitionManager.beginDelayedTransition(
            binding.card,
            transitionSet
        )
        changeTextVisibility(showText)
    }

    enum class ShowText { SHORT, LONG }
    private fun changeTextVisibility(showText: ShowText) {
        when (showText) {
            ShowText.SHORT -> {
                binding.shortText.isVisible = true
                binding.longText.isVisible = false
            }
            ShowText.LONG -> {
                binding.shortText.isVisible = false
                binding.longText.isVisible = true
            }
        }
    }
}
  
<?xml version="1.0" encoding="utf-8"?>
...
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        ...>

        <TextView
            android:id="@+id/short_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            ... />

        <TextView
            android:id="@+id/long_text"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="gone"
            .../>

    </androidx.constraintlayout.widget.ConstraintLayout>

予測型「戻る」遷移を使用する場合は、次の点に注意してください。

  • isSeekingSupported を使用して、遷移が予測型「戻る」をサポートしているかどうかを確認します。
  • カスタム遷移について true を返すように isSeekingSupported をオーバーライドします。
  • アニメーションごとに 1 つのコントローラを作成します。
  • 予測型「戻る」遷移は AndroidX 遷移でサポートされていますが、フレームワーク遷移ではサポートされていません。フレームワーク遷移から移行することをおすすめします。
  • 予測型「戻る」遷移は Android 14 以降を搭載したデバイスでサポートされており、下位互換性はありません。
  • XML シーンで作成された遷移もサポートされています。handleOnBackStarted で、TransitionSeekControllercontrolDelayedTransition の結果ではなく TransitionManager.createSeekController の結果に設定します。

Android 14 以降でカスタム アクティビティ遷移を追加する

Android 14 以降でカスタムのアクティビティ遷移で予測型「戻る」をサポートするには、overridePendingTransition ではなく overrideActivityTransition を使用します。つまり、ユーザーが後方にスワイプすると、遷移アニメーションが再生されます。

この仕組みを示す例として、アクティビティ B がバックスタック内のアクティビティ A の上に重ねられている場合を考えます。カスタム アクティビティ アニメーションは次のように処理します。

  • アクティビティ B の onCreate メソッド内で、開始遷移または終了遷移を呼び出します。
  • ユーザーがアクティビティ B に移動する場合は、OVERRIDE_TRANSITION_OPEN を使用します。ユーザーがスワイプしてアクティビティ A に戻る場合は、OVERRIDE_TRANSITION_CLOSE を使用します。
  • OVERRIDE_TRANSITION_CLOSE を指定した場合、enterAnim はアクティビティ A の開始アニメーション、exitAnim はアクティビティ B の終了アニメーションです。

フラグメントで予測型「戻る」のサポートを追加する

フラグメントで予測型「戻る」を実装する場合、2 つのアプローチがあります。

既存の API を使用する

既存の API を使用することをおすすめします。これらの API を使用すると、画面の端からスワイプすることで、Animator や Androidx の遷移をジェスチャーで操作できます。しきい値を超えて操作したかどうかによって、操作が完了して前のフラグメントに戻るか、またはキャンセルされて現在のフラグメントに残るかが決まります。詳細については、アニメーションを使用してフラグメント間を移動するをご覧ください。

次の点に留意してください。

  • Transitions 1.5.0 以降と Fragment 1.7.0 以降をインポートします。Fragment 内の予測型「戻る」サポートの多くは、アニメーションをシークできる Transitions を使用しています(Transitions 1.5.0 以降でのみ可能)。
  • Fragment を FragmentManager または Navigation コンポーネントとともに使用して、バックスタックを処理します。バックスタックを独自で管理している場合、予測型「戻る」はサポートされません。
  • 一部のライブラリには、予測型「戻る」のサポートが含まれています。ドキュメントをご確認ください。
  • Animator クラスと AndroidX Transition ライブラリがサポートされています。
  • Animation クラスとフレームワーク Transition ライブラリはサポートされていません。
  • 予測型アニメーションは、Android 14 以降を搭載したデバイスでのみ機能します。

予測型「戻る」のクロス フラグメントは、次のような状況で使用します。

1.12.02-alpha02 以降、一部のマテリアル モーションMaterialFadeThroughMaterialSharedAxisMaterialFade など)は、予測型「戻る」をサポートしています。MaterialContainerTransform は予測型「戻る」をサポートしていません。

コールバックを使用する

コールバックを使用してフラグメント間の遷移を作成できますが、コールバックを使用する場合、ユーザーが戻るときに前のフラグメントを確認できないという既知の制限があります。予測型「戻る」の設計ガイダンスに対応するフラグメント間共有要素遷移を作成する手順は次のとおりです。

OnBackPressedCallback を作成します。handleOnBackProgressed 内で、フラグメントのスケーリングとシフトを行います。次に、バックスタックからポップします。次に、コールバックの外部で setSharedElementReturnTransition を使用して、共有要素の遷移を実行します。

詳細については、GitHub のコードサンプルをご覧ください。

要件

次の表に、開発者向けオプション、targetSdkVersioncompileSdkVersion、デバイスのバージョン、依存関係、マニフェスト フラグ、フラグメント フラグで制御される内容を示します。最初の表はコード要件を示しています。

カテゴリ アニメーション compileSdk targetSdk android:enableOnBackInvokedCallback 依存関係
システム アニメーション ホームに戻る 33 すべて なし
クロス アクティビティ 34 すべて なし
クロスタスク 34 すべて なし
プラットフォーム カスタムのクロス アクティビティ 34 すべて なし
Progress API プラットフォーム 34 すべて なし
マテリアル コンポーネント ボトムシート 34 すべて Material Component 1.10.0
サイドシート 34 すべて Material Component 1.10.0
ナビゲーション ドロワー 34 すべて Material Component 1.10.0
検索 34 すべて Material Component 1.10.0
Jetpack アニメーション カスタムの AndroidX のクロス フラグメント 34 すべて AndroidX Fragment 1.7
カスタムの AndroidX の遷移 34 すべて AndroidX Transition 1.5
Progress API Jetpack 34 すべて AndroidX Activity 1.8

次の表に、ユーザーにアニメーションを表示するための要件を示します。

カテゴリ アニメーション 開発者向けオプションが有効 デバイスのバージョン
システム アニメーション ホームに戻る 33
クロス アクティビティ 34
クロスタスク 34
プラットフォーム カスタムのクロス アクティビティ 34
Progress API プラットフォーム × 34
マテリアル コンポーネント ボトムシート × 34
サイドシート × 34
ナビゲーション ドロワー × 34
検索 × 34
Jetpack アニメーション カスタムの AndroidX のクロス フラグメント × 34
カスタムの AndroidX の遷移 × 34
Progress API Jetpack × 34

その他のリソース