Navigation Composeは、Jetpack Composeで構築されたAndroidアプリケーション内部での宣言的ナビゲーションのためのJetpackライブラリです。FragmentManagerやIntentベースのナビゲーションの代わりに、Navigation ComposeはNavControllerとNavHostを介して管理される単一のルートグラフを提供します。Google I/O(2025)によると、Navigation ComposeはComposeアプリケーションの推奨ナビゲーション方法であり、新規プロジェクトの70%以上で使用されています。このライブラリは、型指定された引数の受け渡し、ディープリンク、トランジションアニメーション、SavedStateHandleを介したViewModelとの統合をサポートしています。
重要ポイント
Navigation Composeは、Composeアプリケーションにナビゲーションフレームワークを提供するJetpackスイートのライブラリです。このライブラリはViewシステム用のNavigation Componentと同じ原理に基づいていますが、Composeの宣言的な性質に適応しています。FragmentTransactionの代わりにcomposable関数が使用され、ナビゲーショングラフはKotlin DSLを介して構築されます。
Navigation Composeと従来のナビゲーションの主な違いは、FragmentManagerが不要なことです。各画面はcomposable関数であり、ルートが一致するとNavHostでレンダリングされます。バックスタックはFragmentではなく、ルート、引数、状態を含むレコードを保存します。これによりアーキテクチャが簡素化され、Fragmentベースのナビゲーションに特有のライフサイクルの競合が排除されます。
Google(2025)によると、Navigation Composeは実験段階から安定版へと移行し、バージョン2.8.0以降Jetpackの一部となっています。このライブラリはMaterial3、型安全ナビゲーション(Kotlin Serialization経由)、ネストされたグラフ、モジュール化をサポートしています。唯一の制限は、手動設定なしではBottomNavigationのマルチバックスタックをサポートしていないことですが、Googleはこれに取り組んでいます。
Navigation Composeのアーキテクチャは3つのエンティティを中心に構成されています。NavController(スタック管理)、NavHost(グラフコンテナ)、NavDestination(composableを持つ個別のルート)です。それらの間の相互作用は宣言的です。開発者がルートと引数を記述し、ライブラリが読み込み、保存、復元の状態を処理します。
NavControllerはNavigation Composeの中心的な要素であり、ナビゲーションスタックを管理します。rememberNavController()を介して作成され、NavHostに渡されます。NavControllerはバックスタック、現在のエントリポイントを保存し、遅延アクション(グラフ初期化後のディープリンク)をサポートします。
@Composable
fun AppNavigation() {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = "home") {
composable("home") { HomeScreen(navController) }
composable("profile/{userId}") { backStackEntry ->
ProfileScreen(
userId = backStackEntry.arguments?.getString("userId") ?: ""
)
}
}
}
NavControllerの主要メソッド:navigate(route) — ルートに移動、popBackStack() — 前の画面に戻る、navigateAndClear(route) — スタックをクリアして移動。NavOptionsは動作を指定します:launchSingleTopは重複を防止、popUpToは指定されたルートまでスタックをクリア、restoreStateは以前の状態を復元します。
深くネストされたcomposable関数からNavControllerにアクセスするには、CompositionLocalを介してNavHostControllerを使用します。LocalNavControllerはNavHost内のScopedNavControllerで提供されます。NavHostの外側(例:BottomNavigation)では、コントローラーはパラメーターまたはViewModelを介して渡されます。
NavHostは、NavControllerをルートグラフに結び付けるcomposableコンテナです。各ルートはcomposable(route, arguments, deepLinks)を介して宣言されます。ここでrouteは、オプションの{param}プレースホルダーを持つルート文字列です。現在のルートが一致すると、NavHostは対応するcomposableブロックをレンダリングします。
ルートグラフは階層的に構築されます。モジュール内でルートをグループ化するために、navigation()を介してグラフをネストできます。ネストされたグラフは独自の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) }
}
}
NavHostはLocalBackDispatcherを介してシステムの戻るボタン(バックプレス)を自動的に処理します。Material3 Scaffoldでは、デフォルトでNavControllerを取得してBottomNavigationを正しく動作させます。NavHostはルートが変更されるとcomposableを再作成しますが、rememberSaveableを介して入力フィールドとスクロールの状態を保持します。
Navigation Composeは、ルートパラメーターとNavTypeを介して画面間での型指定された引数の受け渡しをサポートしています。パラメーターはルート内で{paramName}として指定され、composable()のargumentsを介して型が指定されます。NavTypeはString、Int、Long、Float、Boolean、Parcelable、Serializableをサポートしています。
| 引数の型 | NavType | ルートの例 |
|---|---|---|
| String | NavType.StringType | "profile/{name}" |
| Int | NavType.IntType | "item/{id}" |
| Boolean | NavType.BoolType | "settings?enabled={flag}" |
| Parcelable | NavType.ParcelableType | "details/{item}" |
| Float | NavType.FloatType | "map?lat={lat}&lng={lng}" |
引数はNavBackStackEntryからarguments?.getType(key)を介して抽出されます。必須パラメーターにはdefaultValueを使用し、オプションのパラメーターにはnullableを使用します。ParcelableのサポートはKotlin Parcelizeまたはkotlinx.parcelizeライブラリでのみ機能します。複雑なオブジェクトの場合は、オブジェクト全体をシリアライズするのではなく、IDを渡してViewModelを介してデータをロードすることをお勧めします。
Navigation 2.8.0以降、Kotlin Serializationを使用した型安全ナビゲーションが導入されました。ルートはデータクラスとして定義され、引数はフィールドとして定義されます。これにより、文字列ルートが型指定されたオブジェクトに置き換えられ、ルート名のエラーが排除されます。移行にはKotlin Serializationプラグインとnavigation-compose-typesafe依存関係が必要です。
@Serializable
/* sealed class Route */
sealed class ProfileRoute(val route: String) {
data object Home : ProfileRoute("home")
data class Profile(val userId: String) : ProfileRoute("profile/{userId}")
}
ディープリンクは、URLまたはintent-filterを介して特定のアプリケーション画面を開くことを可能にするナビゲーションメカニズムです。Navigation Composeでは、ディープリンクはcomposable()のdeepLinksパラメーターを介して設定され、URIがパターンと一致すると自動的に処理されます。
ディープリンクはUriPatternリストとして指定されます:"https://example.com/profile/{userId}"。URIパラメーターは自動的にルート引数にマッピングされます。NavControllerはアプリケーション起動時(intent経由)と実行中(暗黙的ディープリンク経由)でディープリンクを処理します。保留中のディープリンクを処理するには、グラフ初期化後にNavControllerでhandleDeepLink()を使用します。
Googleによると、ディープリンクは以下に推奨されています:プッシュ通知(Firebase Dynamic Links)、メール確認、コンテンツ共有、Webリンクからのクロスナビゲーション。Android 12+では、ディープリンクの権限を検証するためにDigital Asset Linksが使用されます。AndroidManifest.xmlには、ダイアログなしでリンクを開くためにautoVerify="true"のintent-filterを含める必要があります。
composable(
route = "profile/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.StringType }),
deepLinks = listOf(
navDeepLink { uriPattern = "https://example.com/profile/{userId}" }
)
) { backStackEntry ->
ProfileScreen(userId = backStackEntry.arguments?.getString("userId") ?: "")
}
Navigation Composeでのディープリンクの制限:ライブラリは遅延ディープリンクをサポートしていません。ディープリンクはNavHostがグラフを完全に構築した後にのみ処理されます。グラフ初期化前にディープリンクが到着した場合は、intent?.dataを介して遅延させ、LaunchedEffectで処理する必要があります。Firebase Dynamic Linksの場合は、Navigation Composeと一緒にFirebase Dynamic Links SDKを使用してください。
Navigation Composeは、composable()のenterTransition、exitTransition、popEnterTransition、popExitTransitionパラメーターを介してトランジションアニメーションをサポートしています。アニメーションはCompose Animation API(fadeIn、slideInHorizontally、expandInなど)を使用して実装されます。デフォルトではアニメーションは無効になっており、画面は即座に切り替わります。
一般的なアニメーションシナリオ:前方ナビゲーションにはslideInHorizontally(画面が右からスライドイン)、戻るにはslideOutHorizontally(画面が右にスライドアウト)。BottomNavigationでは、スライドなしのフェードアニメーションがより一般的に使用されます。アニメーションはNavHostを介して設定され、個別に指定されない限りすべてのcomposableに適用されます。
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally() + fadeIn() },
exitTransition = { slideOutHorizontally() + fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }
アニメーションパラメーターをcomposable()に直接渡すことで、各composableごとに個別にアニメーションを上書きできます。重要なのは、アニメーションがシステムのバックプレスアニメーションと競合しないことです。共有要素トランジションには、accompanist-navigation-animationライブラリまたはModifier.graphicsLayerを介したカスタム実装が必要です。Android Developers(2025)によると、本番アプリケーションの80%が標準ナビゲーションに水平スライドアニメーションを使用しています。
よくある質問
Navigation ComposeはFragmentなしで動作し、グラフにcomposable関数とKotlin DSLを使用します。Navigation Component(View)はFragmentManagerとXMLグラフに基づいています。Composeバージョンはよりシンプルで高速で、Fragmentのライフサイクルがありません。View用のNavigation Componentはハイブリッドアプリケーションにのみ適しています。
オブジェクトのIDを渡し、SavedStateHandleを使用してViewModelを介してデータをロードすることをお勧めします。オブジェクトが単純な場合は、kotlinx.parcelizeを介してParcelableを使用してください。引数(Bundle)を介して大きなオブジェクトを直接渡すと、〜1 MBの制限があり、TransactionTooLargeExceptionが発生する可能性があります。
はい、NavHost内のnavigation(route, startDestination)関数を介してサポートしています。ネストされたグラフは独自のstartDestinationを持ち、共通のルートプレフィックスの下で結合されます。これにより、各機能モジュール用に分離されたグラフを持つモジュラーアーキテクチャを編成できます。
NavControllerはComposeのBackHandlerを介してバックプレスを自動的に処理します。戻るが押されたらnavController.popBackStack()を呼び出します。カスタム処理(終了確認)の場合は、popBackStack()を呼び出す前にBackHandler(enabled = condition) { callback }を使用します。
現在、Navigation ComposeはCompose Multiplatformでサポートされていません。クロスプラットフォームプロジェクトのiOS部分には、VoyagerまたはDecomposeを使用してください。GoogleはKMPサポートに取り組んでいますが、リリース時期は未定です。Androidのみのプロジェクトでは、Navigation Composeが唯一の推奨オプションです。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。