NavHostは、Jetpack Composeのナビゲーショングラフのエントリポイントとして機能するcomposableコンテナです。NavControllerを一連のルートにリンクし、バックスタックの状態に基づいて現在の画面をレンダリングします。Android Developers(2025)によると、NavHostはナビゲーションを備えたComposeアプリケーションに必須のコンポーネントです。NavHost内では、オプションの引数、ディープリンク、アニメーションとともにcomposableルートが登録されます。各ルートは、遷移データを持つNavBackStackEntryを受け取る通常のcomposable関数です。NavHostは、バックプレス、状態の保存、再構成時の復元を自動的に処理します。
重要なポイント
NavHostは、現在のナビゲーション画面を表示するためのコンテナを提供するcomposable関数です。NavHostは、NavController、startDestination、およびKotlin DSLで構築されたルートグラフを受け取ります。現在のルートが変更されると、NavHostは指定されたアニメーションで表示されるcomposableを切り替えます。
NavHostは画面スイッチャーとして機能します。NavControllerから現在のNavBackStackEntryを追跡し、対応するcomposableブロックをレンダリングします。各画面は独立したcomposable関数であり、ルート引数を持つNavBackStackEntryを受け取ります。すべての画面は単一のコンポジションツリーに存在しますが、NavHostは一度に1つだけを表示し、他の画面はアニメーションで非表示にします。
FragmentManagerとは異なり、NavHostは画面ごとにFragmentを作成しません。ライフサイクル全体はCompositionLifecycleを介して管理されます。composable関数にはonStart/onResumeがないため、副作用にはLaunchedEffectとDisposableEffectが使用されます。NavHostは自動的にNavControllerを購読し、ルートが変更されるとUIを再コンポーズします。
Googleによると、NavHostはNavigation 2.4.0以降の安定したAPIです。2.8.0以降、NavHostはKotlin Serializationを介したタイプセーフナビゲーションをサポートし、文字列ルートをデータクラスに置き換えます。NavHostはネストされたグラフもサポートしており、モジュールベースのナビゲーション編成を可能にします。
NavHostは2つの必須パラメータで作成されます。navController(NavHostControllerのインスタンス)とstartDestination(最初の画面のルート文字列)です。3番目のパラメータは、composable()、navigation()、dialog()を介してすべてのルートが登録されるビルダーブロックです。
@Composable
fun AppNavHost(navController: NavHostController) {
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") { HomeScreen(navController) }
composable("settings") { SettingsScreen(navController) }
}
}
startDestinationは、NavHostが最初に起動されたときに開くルートです。バックスタックが空の場合、NavHostは自動的にstartDestinationをスタックに追加します。再構成(画面回転)時、NavHostはsavedStateから最後のルートを復元し、startDestinationは復元しません。
BottomNavigationの場合、startDestinationは下部パネルのルートの1つです。残りのパネルルートは個別のcomposableエントリとして追加されます。NavHostはScaffold.content内に配置する必要があります。ここにメインのアプリケーションコンテンツが表示されます。NavHostは、TopAppBarとBottomNavigationを除いた利用可能な高さをすべて占有します。
composable(route, arguments, deepLinks, enterTransition, exitTransition, content)関数は、NavHostグラフにルートを登録します。routeパラメータは、{paramName}形式のオプションのプレースホルダーを持つパスを記述する文字列です。ナビゲーション中にプレースホルダーは実際の値に置き換えられます。
composableのcontentブロックは、引数が抽出されるNavBackStackEntryを受け取ります。画面のcomposable関数は、現在のNavControllerルートがルートと一致する場合にのみレンダリングされます。一致しない場合、composableはコンポジションから削除されますが、その状態はrememberSaveableまたはSavedStateHandle付きのViewModelを介して保存できます。
composable(
route = "article/{articleId}",
arguments = listOf(navArgument("articleId") {
type = NavType.IntType
defaultValue = 0
}),
deepLinks = listOf(navDeepLink { uriPattern = "https://app.example/article/{articleId}" })
) { backStackEntry ->
val articleId = backStackEntry.arguments?.getInt("articleId") ?: 0
ArticleScreen(articleId = articleId)
}
NavHost内のcomposableエントリの数は、数個から数百個までさまざまです。大規模なアプリケーションの場合、ルートはモジュール間で分割され、ネストされたグラフを介して接続されます。各composableは、独自のアニメーション設定、ディープリンク、引数を持つことができます。
ルート引数は、composable()のarguments: List<NamedNavArgument>パラメータを介して定義されます。各引数は、navArgument(name) { type; defaultValue }を介して定義されます。NavTypeは引数の型を決定します:StringType、IntType、LongType、FloatType、BoolType、ParcelableType、ReferenceType。
| ルートパラメータ | ルートの例 | NavType |
|---|---|---|
| パス(path) | "user/{id}" | NavType.IntType |
| クエリ(query) | "search?q={query}" | NavType.StringType |
| オプション | "details/{id}?tab={tab}" | StringType + defaultValue="" |
| Parcelable | "checkout/{order}" | NavType.ParcelableType |
引数は、arguments?.getInt("id")を介してNavBackStackEntryから抽出されます。必須引数の場合、defaultValueは省略できます。NavTypeはnullを使用します。オプション引数の場合、defaultValueを設定する必要があります。そうしないと、パラメータが欠落している場合にナビゲーションが例外をスローします。
Navigation 2.8.0以降、タイプセーフナビゲーションが推奨されています。Kotlin Serializationを使用して、ルートのシールドクラスまたはデータクラスを定義します。文字列ルートの代わりに、composable<RouteType> { backStackEntry -> }を使用します。これにより、ルートのタイプミスがなくなり、引数のNavTypeが自動的に生成されます。移行するには、navigation-compose-typesafe依存関係とKotlin Serializationプラグインを追加します。
nested graphs — navigation(route, startDestination)関数を使用してNavHost内でルートをグループ化するメカニズム。ネストされたグラフには独自のルートプレフィックスとstartDestinationがあり、そのすべてのルートはプレフィックスを介してアクセスできます。ネストされたグラフはモジュラーアーキテクチャに使用され、各フィーチャーモジュールが独自のサブグラフを登録します。
ネストされたグラフの利点:モジュール内のルートの分離、画面グループの統一されたバックスタック、内部構造を公開せずにプレフィックスでナビゲートする機能。たとえば、「auth」グラフには「auth/login」と「auth/register」が含まれます。ナビゲーションは、完全なルート、またはstartDestinationへのリダイレクト付きのプレフィックスのいずれかで可能です。
NavHost(navController = navController, startDestination = "main") {
composable("main") { MainScreen(navController) }
navigation(
route = "auth",
startDestination = "auth/login"
) {
composable("auth/login") { LoginScreen(navController) }
composable("auth/register") { RegisterScreen(navController) }
}
}
ネストされたグラフは、グラフレベルでの引数渡しをサポートします。グラフのルートで宣言されたパラメータは、すべての内部ルートに渡されます。ネストされたグラフをクリアするには、popBackStack(route)を使用します。これにより、すべての内部エントリが削除されます。ネストされたグラフに深さの制限はありませんが、読みやすさのために3レベル以内が推奨されます。
NavHostは、enterTransition、exitTransition、popEnterTransition、popExitTransitionパラメータを介してcomposableルート間の遷移アニメーションをサポートします。アニメーションは一度NavHostに設定され、すべてのルートに適用されるか、各composableに個別に適用されます。デフォルトでは、アニメーションは無効です。
一般的な設定:enterTransition = slideInHorizontally(initialOffsetX = { it }) — 画面が右からスライドインします。exitTransition = slideOutHorizontally(targetOffsetX = { -it }) — 画面が左にスライドアウトします。ポップアニメーションの場合、方向が反転します。画面は左からスライドインし、右にスライドアウトします。BottomNavigationの場合は、スライドなしでfadeIn/fadeOutが使用されます。
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally(initialOffsetX = { it }) + fadeIn() },
exitTransition = { slideOutHorizontally(targetOffsetX = { -it }) + fadeOut() },
popEnterTransition = { slideInHorizontally(initialOffsetX = { -it }) + fadeIn() },
popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) + fadeOut() }
) { /* composable routes */ }
カスタムアニメーションはCompose Animation APIを使用して作成されます。AnimatedContentTransitionScopeは、コンテナの寸法、アニメーションの進行状況、方向へのアクセスを提供します。共有要素遷移(1つの要素が別の画面にスムーズに移動する)には、Accompanist Navigation Animationライブラリ、またはsharedElement Modifierを介したカスタム実装が必要です。Android Developers(2025)によると、デフォルトのスライドアニメーション(右から入り、左に出る)は、ナビゲーションを備えたAndroidアプリの80%で使用されています。
よくある質問
技術的には可能ですが、推奨されません。各NavHostは独立したバックスタックを作成し、統一されたナビゲーションを壊します。例外は、メインコンテンツ用のNavHostと、独自のナビゲーションを持つBottomSheet用のNavHostなど、分離された領域です。
NavHostは画面を切り替えるナビゲーションコンテナです。Scaffoldはページ全体のレイアウト(TopAppBar、BottomNavigation、FloatingActionButton)です。通常、NavHostはScaffold.content内に配置されます。Scaffoldはナビゲーションを管理せず、UIコンポーネントのスロットを提供するだけです。
ViewModelはNavBackStackEntry内でviewModel()を介して作成されます。画面間でViewModelを共有するには、parentNavControllerを使用します。共有ViewModelを親エントリにバインドします。代替手段は、NavGraphスコープを持つDI(Hilt/Koin)です。
これは通常の動作です。ルートを離れる際に、NavHostはcomposableをコンポジションから削除します。状態を保持するには、UI状態にはrememberSaveableを、ビジネスロジックにはSavedStateHandle付きのViewModelを使用します。
最後のルートとしてcomposable("404")を追加し、不明なディープリンクを受信したときにそこにナビゲートします。NavHostにはキャッチオールルートがありません。navigate()の前に、ディープリンクのインテントハンドラでルートを確認します。ルートが見つからない場合は、404にナビゲートします。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。