Navigation Compose — це бібліотека Jetpack для декларативної навігації всередині Android-застосунків, побудованих на Jetpack Compose. Замість FragmentManager або Intent-орієнтованої навігації Navigation Compose пропонує єдиний граф маршрутів, керований через NavController та NavHost. За даними Google I/O (2025), Navigation Compose — рекомендований спосіб навігації для Compose-застосунків, що використовується більш ніж у 70% нових проєктів. Бібліотека підтримує передачу типізованих аргументів, глибокі посилання, анімацію переходів та інтеграцію з ViewModel через SavedStateHandle.
Головне
Navigation Compose — це бібліотека зі складу Jetpack, що надає навігаційний фреймворк для Compose-застосунків. Бібліотека базується на тих самих принципах, що й Navigation Component для View-системи, але адаптована під декларативну природу Compose: замість FragmentTransaction використовуються composable-функції, а граф навігації будується через Kotlin DSL.
Ключова відмінність Navigation Compose від класичної навігації — відсутність FragmentManager. Кожен екран — це composable-функція, яка рендериться в NavHost при збігу маршруту. Back stack зберігає не Fragment, а запис із route, аргументами та станом. Це спрощує архітектуру та виключає lifecycle-конфлікти, характерні для Fragment-навігації.
За даними Google (2025), Navigation Compose пройшов шлях від experimental до stable і входить до складу Jetpack з версії 2.8.0. Бібліотека підтримує Material3, Type-Safe Navigation (через Kotlin Serialization), вкладені графи та модуляризацію. Єдине обмеження — бібліотека не підтримує multi-back stack для BottomNavigation без ручного налаштування, хоча Google працює над цим.
Архітектура Navigation Compose будується навколо трьох сутностей: NavController (керування стеком), NavHost (контейнер графа) та NavDestination (окремий маршрут із composable). Взаємодія між ними декларативна: розробник описує маршрути та аргументи, а бібліотека обробляє стани завантаження, збереження та відновлення.
NavController — центральний елемент Navigation Compose, що керує навігаційним стеком. Створюється через rememberNavController() і передається в NavHost. NavController зберігає back stack, поточну точку входу та підтримує відкладені дії (deeplink після ініціалізації графа).
@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 відновлює попередній стан.
Для доступу до NavController із глибоко вкладених composable-функцій використовуйте NavHostController через CompositionLocal. LocalNavController надається в ScopedNavController всередині NavHost. Поза NavHost (наприклад, в BottomNavigation) контролер передається через параметри або ViewModel.
NavHost — це composable-контейнер, який пов'язує NavController з графом маршрутів. Кожен маршрут оголошується через composable(route, arguments, deepLinks), де route — рядок маршруту з опціональними плейсхолдерами {param}. При збігу поточного маршруту з route NavHost рендерить відповідний composable-блок.
Граф маршрутів будується ієрархічно: можна вкладати графи через navigation() для групування маршрутів всередині модуля. Вкладені графи мають власний startDestination і об'єднуються під спільним route-префіксом. Це дозволяє організувати модульну архітектуру, де кожен feature-модуль реєструє свій підграф.
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 автоматично обробляє системну кнопку Back (back press) через LocalBackDispatcher. У Material3 Scaffold за замовчуванням підхоплює NavController для коректної роботи BottomNavigation. NavHost перестворює composable при зміні маршруту, але зберігає стан через rememberSaveable для полів введення та скролу.
Navigation Compose підтримує передачу типізованих аргументів між екранами через маршрутні параметри та NavType. Параметри задаються в route як {paramName} із зазначенням типу через arguments в composable(). NavType підтримує String, Int, Long, Float, Boolean, Parcelable та Serializable.
| Тип аргументу | NavType | Приклад route |
|---|---|---|
| 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 з'явилася Type-Safe Navigation з Kotlin Serialization: маршрути визначаються як data-класи, а аргументи — як поля. Це замінює рядкові route на типізовані об'єкти та виключає помилки в іменах маршрутів. Для міграції потрібен плагін 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 глибокі посилання налаштовуються через параметр deepLinks в composable() і обробляються автоматично при збігу URI з шаблоном.
Глибоке посилання задається як список UriPattern: "https://example.com/profile/{userId}". Параметри з URI автоматично мапляться в аргументи маршруту. NavController обробляє глибоке посилання при старті застосунку (через intent) та в процесі роботи (через неявні глибокі посилання). Для обробки відкладених глибоких посилань використовується handleDeepLink() в NavController після ініціалізації графа.
За даними Google, глибокі посилання рекомендується налаштовувати для: пушів (Firebase Dynamic Links), верифікації email, поширення контенту та наскрізної навігації з веб-посилань. Для Android 12+ використовується Digital Asset Links для верифікації авторитетності глибокого посилання. AndroidManifest.xml повинен містити intent-filter з autoVerify="true" для відкриття посилань без діалогу.
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 використовуйте Firebase Dynamic Links SDK у зв'язці з Navigation Compose.
Navigation Compose підтримує анімацію переходів через параметри enterTransition, exitTransition, popEnterTransition та popExitTransition в composable(). Анімації реалізуються через Compose Animation API: fadeIn, slideInHorizontally, expandIn та інші. За замовчуванням анімація вимкнена — екрани замінюються миттєво.
Типові сценарії анімації: slideInHorizontally для навігації вперед (екран заїжджає справа), slideOutHorizontally для повернення (екран виїжджає вправо). Для BottomNavigation частіше використовується fade-анімація без слайду. Анімації задаються через NavHost і застосовуються до всіх composable, якщо не вказані індивідуальні.
NavHost(
navController = navController,
startDestination = "home",
enterTransition = { slideInHorizontally() + fadeIn() },
exitTransition = { slideOutHorizontally() + fadeOut() },
popEnterTransition = { fadeIn() },
popExitTransition = { slideOutHorizontally() + fadeOut() }
) { /* composable */ }
Анімації можна перевизначити для кожного composable індивідуально, передавши анімаційні параметри прямо в composable(). Важливо: анімації не повинні конфліктувати з системною анімацією back press. Для shared element transition потрібна бібліотека accompanist-navigation-animation або кастомна реалізація через Modifier.graphicsLayer. За даними Android Developers (2025), 80% production-застосунків використовують горизонтальну слайд-анімацію для стандартної навігації.
Часті запитання
Navigation Compose працює без Fragment, використовуючи composable-функції та Kotlin DSL для графа. Navigation Component (View) базується на FragmentManager та XML-графах. Compose-версія простіша, швидша та не має життєвих циклів Fragment. Navigation Component для View підходить тільки для гібридних застосунків.
Рекомендується передавати ID об'єкта та завантажувати дані через ViewModel з SavedStateHandle. Якщо об'єкт простий — використовуйте Parcelable через kotlinx.parcelize. Передача великих об'єктів безпосередньо через аргументи (Bundle) обмежена лімітом ~1 MB і може викликати TransactionTooLargeException.
Так, через функцію navigation(route, startDestination) всередині NavHost. Вкладені графи мають власний startDestination і об'єднуються під спільним route-префіксом. Це дозволяє організувати модульну архітектуру з ізольованими графами для кожного feature-модуля.
NavController автоматично обробляє back press через BackHandler з Compose. Викличте navController.popBackStack() при натисканні Back. Для кастомної обробки (підтвердження виходу) використовуйте BackHandler(enabled = condition) { callback } до виклику popBackStack().
Наразі Navigation Compose не підтримується в Compose Multiplatform. Для iOS-частини крос-платформових проєктів використовуйте Voyager або Decompose. Google працює над підтримкою KMP, але термінів випуску немає. Для Android-only проєктів Navigation Compose — єдиний рекомендований варіант.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також