デスティネーション間のアニメーション

NavDisplay には、ユーザーがアプリ内を移動する際にスムーズな視覚的な遷移を作成するためのアニメーション機能が組み込まれています。これらのアニメーションは、メタデータを使用して NavDisplay に対してグローバルに、または NavEntry ごとにカスタマイズできます。

デフォルトの遷移をオーバーライドする

NavDisplayContentTransform を使用して、ナビゲーション中のコンテンツのアニメーション方法を定義します。デフォルトのアニメーション動作をオーバーライドするには、NavDisplay に遷移パラメータを指定します。

  • transitionSpec: このパラメータは、コンテンツがバックスタックに追加されるとき(つまり、前方に移動するときに)適用する ContentTransform を定義します。
  • popTransitionSpec: このパラメータは、コンテンツがバックスタックから削除されたとき(「戻る」を操作したとき)に適用する ContentTransform を定義します。
  • predictivePopTransitionSpec: このパラメータは、予測型「戻る」ジェスチャーを使用してコンテンツがポップされたときに適用する ContentTransform を定義します。

個々の NavEntry レベルで遷移をオーバーライドする

メタデータを使用して、特定の NavEntry のカスタム アニメーションを定義することもできます。NavDisplay は、エントリごとの遷移を適用する特別なメタデータキーを認識します。

  • NavDisplay.transitionSpec: このヘルパー関数を使用して、前方ナビゲーション アニメーションを定義します。
  • NavDisplay.popTransitionSpec: このヘルパー関数を使用して、特定の NavEntry の「戻る」ナビゲーション アニメーションを定義します。
  • NavDisplay.predictivePopTransitionSpec: このヘルパー関数を使用して、特定の NavEntry の予測型「戻る」ジェスチャーのアニメーションを定義します。

これらのエントリごとのメタデータ遷移は、NavDisplay の同じ名前のグローバル遷移をオーバーライドします。

次のスニペットは、グローバルな NavDisplay 遷移と個々の NavEntry レベルのオーバーライドの両方を示しています。

@Serializable
data object ScreenA : NavKey

@Serializable
data object ScreenB : NavKey

@Serializable
data object ScreenC : NavKey

class AnimatedNavDisplayActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {

            Scaffold { paddingValues ->

                val backStack = rememberNavBackStack(ScreenA)

                NavDisplay(
                    backStack = backStack,
                    onBack = { backStack.removeLastOrNull() },
                    entryProvider = entryProvider {
                        entry<ScreenA> {
                            ContentOrange("This is Screen A") {
                                Button(onClick = { backStack.add(ScreenB) }) {
                                    Text("Go to Screen B")
                                }
                            }
                        }
                        entry<ScreenB> {
                            ContentMauve("This is Screen B") {
                                Button(onClick = { backStack.add(ScreenC) }) {
                                    Text("Go to Screen C")
                                }
                            }
                        }
                        entry<ScreenC>(
                            metadata = NavDisplay.transitionSpec {
                                // Slide new content up, keeping the old content in place underneath
                                slideInVertically(
                                    initialOffsetY = { it },
                                    animationSpec = tween(1000)
                                ) togetherWith ExitTransition.KeepUntilTransitionsFinished
                            } + NavDisplay.popTransitionSpec {
                                // Slide old content down, revealing the new content in place underneath
                                EnterTransition.None togetherWith
                                    slideOutVertically(
                                        targetOffsetY = { it },
                                        animationSpec = tween(1000)
                                    )
                            } + NavDisplay.predictivePopTransitionSpec {
                                // Slide old content down, revealing the new content in place underneath
                                EnterTransition.None togetherWith
                                    slideOutVertically(
                                        targetOffsetY = { it },
                                        animationSpec = tween(1000)
                                    )
                            }
                        ) {
                            ContentGreen("This is Screen C")
                        }
                    },
                    transitionSpec = {
                        // Slide in from right when navigating forward
                        slideInHorizontally(initialOffsetX = { it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { -it })
                    },
                    popTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    predictivePopTransitionSpec = {
                        // Slide in from left when navigating back
                        slideInHorizontally(initialOffsetX = { -it }) togetherWith
                            slideOutHorizontally(targetOffsetX = { it })
                    },
                    modifier = Modifier.padding(paddingValues)
                )
            }
        }
    }
}

図 1. カスタム アニメーションを使用したアプリ。