Navigation Component is an Android Jetpack library for implementing navigation between app screens. The component centralizes management of the fragment stack, deep links, and argument passing. It has been part of Jetpack since 2018 and is recommended by Google for all new projects. Learn more in the official Google guide.
Key Takeaways
Navigation Component is an Android Jetpack library (androidx.navigation) that provides a unified API for navigation. It includes three key elements: Navigation Graph (navigation graph), NavHostFragment (screen container), and NavController (transition controller). The component automatically manages the back stack and supports deep links.
Before Navigation Component, developers managed fragments manually through FragmentManager. This led to fragmented (literally) code: each screen had its own navigation rules, back stack states varied, and deep links required separate implementation. Navigation Component unified these scenarios. According to Google (2026), the library is installed in 90% of new Android projects.
Navigation Component integrates with other Jetpack libraries: LiveData, ViewModel, Material Design. It supports both XML fragments and Jetpack Compose via the navigation-compose extension. Stable release — 2.8.x (2025), minimum Android version — API 14.
NavGraph is an XML resource (res/navigation/nav_graph.xml) that defines all app screens and connections between them. Each screen is a destination, which can be a Fragment, Activity, or Composable. Connections between destinations are actions that define the transition direction.
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@+id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name=".HomeFragment"
android:label="Home"
tools:layout="@layout/fragment_home">
<action
android:id="@+id/action_home_to_detail"
app:destination="@+id/detailFragment"
app:enterAnim="@anim/slide_in_right"
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
</fragment>
<fragment
android:id="@+id/detailFragment"
android:name=".DetailFragment"
android:label="Details"
tools:layout="@layout/fragment_detail">
<argument android:name="itemId"
app:argType="integer"
android:defaultValue="0" />
</fragment>
</navigation>The startDestination attribute sets the first screen displayed on launch. An action defines the target destination and optional animations. Arguments describe parameters passed to the screen — type and default value.
NavHostFragment is a container placed in the Activity layout that displays the current navigation screen. NavHostFragment automatically switches fragments when NavController.navigate() is called. NavController is the object that manages navigation: transitions, back navigation, and current route checking.
// Layout Activity: activity_main.xml
// <androidx.fragment.app.FragmentContainerView
// android:id="@+id/nav_host_fragment"
// android:name="androidx.navigation.fragment.NavHostFragment"
// app:navGraph="@navigation/nav_graph"
// app:defaultNavHost="true" />
class MainActivity : AppCompatActivity() {
private val navController by lazy {
(findViewById<NavHostFragment>(R.id.nav_host_fragment))
.navController
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// NavigationUI connects NavController to AppBar
setupActionBarWithNavController(navController)
}
// Navigate to details screen
fun openDetail(itemId: Long) {
val bundle = Bundle().apply {
putLong("itemId", itemId)
}
navController.navigate(R.id.action_home_to_detail, bundle)
}
override fun onSupportNavigateUp() =
navController.navigateUp() || super.onSupportNavigateUp()
}app:defaultNavHost="true" is an important attribute: it intercepts the system Back button and passes control to NavController. NavigationUI is a utility for linking NavController with AppBar, BottomNavigationView, NavigationDrawer. setupActionBarWithNavController enables the Up arrow on nested screens.
Navigation Component supports custom transition animations, set in actions or programmatically. Animations are defined by four attributes: enterAnim (new screen appearance), exitAnim (current screen disappearance), popEnterAnim (appearance on back navigation), and popExitAnim (disappearance on back navigation).
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="100%"
android:toXDelta="0%"
android:duration="300" />
</set>
// Programmatic transition with animation
val navOptions = NavOptions.Builder()
.setEnterAnim(R.anim.slide_in_right)
.setExitAnim(R.anim.slide_out_left)
.setPopEnterAnim(R.anim.slide_in_left)
.setPopExitAnim(R.anim.slide_out_right)
.build()
navController.navigate(R.id.detailFragment, args, navOptions)Animations work with Fragment at the FragmentTransaction level. For Jetpack Compose, animations are set via NavOptionsCompat using Compose Animation. Navigation Component does not impose restrictions on animation type — translate, scale, alpha and their combinations are supported.
Safe Args is a Gradle plugin for type-safe data transfer between screens. The plugin analyzes NavGraph, generates Directions and Args classes with specific field types. Type matching is checked at compile time — a MissingArgumentException is caught before the app runs.
// build.gradle (module)
plugins {
id 'androidx.navigation.safeargs.kotlin'
}
// Safe Args generates: DetailFragmentArgs, HomeFragmentDirections
// Usage in HomeFragment:
val action = HomeFragmentDirections
.actionHomeToDetail(itemId = 42L)
findNavController().navigate(action)
// Usage in DetailFragment:
private val args: DetailFragmentArgs by navArgs()
// args.itemId is of type Long, null cannot be passed
override fun onViewCreated(...) {
super.onViewCreated(...)
loadItem(args.itemId)
}navArgs() is a Kotlin delegate for retrieving arguments in a Fragment or Activity. The plugin supports primitives, strings, Parcelable, Serializable, Enum, and arrays. For complex objects, pass an ID and load from ViewModel or database.
Deep Link is an external link that opens a specific app screen. Navigation Component handles deep links via the app:deepLink attribute in NavGraph. The system creates a PendingIntent that restores the navigation stack to the target screen, or creates a new stack if the app is not running.
<fragment android:id="@+id/profileFragment"
android:name=".ProfileFragment">
<deepLink
app:uri="https://example.com/profile/{userId}" />
<argument
android:name="userId"
app:argType="string" />
</fragment>
// Programmatic Deep Link creation
val pendingIntent = NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.profileFragment)
.setArguments(Bundle().apply {
putString("userId", "user_123")
})
.createPendingIntent()Deep Links support URI patterns with paths and query parameters, intent action, and mime type. Placeholders ({userId}) are automatically mapped to destination arguments. Navigation Component also handles implicit deep links through AndroidManifest — just add an intent-filter to the Activity with NavHostFragment.
Navigation Compose (androidx.navigation:navigation-compose) is an extension of Navigation Component for Jetpack Compose. The API preserves the NavController and NavHost concept, but screens are Composable functions instead of Fragments. NavHost accepts a composable lambda for each route.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = "home"
) {
composable("home") {
HomeScreen(
onItemClick = { id ->
navController.navigate("detail/$id")
}
)
}
composable(
route = "detail/{itemId}",
arguments = listOf(
navArgument("itemId") {
type = NavType.LongType
}
)
) { backStackEntry ->
val itemId = backStackEntry
.arguments?.getLong("itemId") ?: 0L
DetailScreen(itemId = itemId)
}
}
}
}
}
}Navigation Compose uses string routes instead of ids. Parameters are passed via route templates ("detail/{itemId}") and extracted from backStackEntry. rememberNavController() preserves NavController across recompositions. For Type Safety in Compose, the navigation-compose-type-safety module (experimental) is recommended.
Frequently Asked Questions
NavHost is a container for displaying navigation screens. It is implemented via NavHostFragment in the XML layout. NavHost tracks the current screen in NavGraph and manages transitions. Each Activity contains one NavHostFragment.
Safe Args is a Gradle plugin that generates type-safe argument classes. Bundle requires manual specification of keys and types, leading to runtime errors. Safe Args checks types at compile time and serializes data automatically.
Complex objects are passed through ViewModel (shared across screens) or via a database by passing an ID. Safe Args only supports primitives, strings, and Parcelable. Google recommends avoiding passing large objects through navigation arguments.
A Deep Link is configured in NavGraph via the app:deepLink attribute. Navigation Component automatically handles incoming links, creates a PendingIntent through NavDeepLinkBuilder, and restores the navigation stack to the target screen. Supports URI, intent action, and mime type.
Yes. Navigation Compose (androidx.navigation:navigation-compose) provides NavHost for Compose. The API is similar to the XML version, but screens are Composable functions. NavController is used the same way in both versions. Google recommends Navigation Compose for new Compose projects.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also