¿Qué es Navigation Component?
Navigation Component es la librería oficial de Jetpack para manejar la navegación dentro de una app. Resuelve de forma centralizada y visual tres cosas que antes eran tediosas: las transiciones entre pantallas, el back stack, y el pasaje de argumentos.
Sus tres pilares son:
- NavGraph: un archivo XML que define todas las pantallas y las conexiones entre ellas (como un mapa de la app).
- NavHostFragment: el contenedor en tu Activity donde van a mostrarse los Fragments.
- NavController: el objeto con el que navegás desde el código.
Configuración
// build.gradle (app)
dependencies {
val nav_version = "2.7.7"
implementation("androidx.navigation:navigation-fragment-ktx:$nav_version")
implementation("androidx.navigation:navigation-ui-ktx:$nav_version")
}
El NavGraph
Creá el archivo en res/navigation/nav_graph.xml (click derecho en res → New → Android Resource File → tipo Navigation):
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@id/homeFragment">
<fragment
android:id="@+id/homeFragment"
android:name="ar.pensa.app.HomeFragment"
android:label="Inicio">
<!-- Acción para navegar al detalle -->
<action
android:id="@+id/action_home_to_detalle"
app:destination="@id/detalleFragment" />
</fragment>
<fragment
android:id="@+id/detalleFragment"
android:name="ar.pensa.app.DetalleFragment"
android:label="Detalle">
<argument
android:name="productoId"
app:argType="integer" />
</fragment>
</navigation>
NavHostFragment en la Activity
En el layout de tu MainActivity, reemplazás todo por un NavHostFragment que actúa como contenedor:
<!-- activity_main.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navHostFragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
app:defaultNavHost="true" hace que este NavHost intercepte el botón Back del sistema.
Navegar entre Fragments
Desde cualquier Fragment obtenés el NavController y llamás a navigate():
// Navegación simple por ID de acción:
binding.btnVerDetalle.setOnClickListener {
findNavController().navigate(R.id.action_home_to_detalle)
}
// Con Safe Args (recomendado — ver lección 02):
binding.btnVerDetalle.setOnClickListener {
val accion = HomeFragmentDirections.actionHomeToDetalle(productoId = 42)
findNavController().navigate(accion)
}
// Volver atrás:
findNavController().navigateUp()
// o simplemente el botón Back del sistema lo hace automáticamente
findNavController()Esta función de extensión está disponible directamente en cualquier Fragment. También podés obtener el NavController desde la Activity: navController = findNavController(R.id.navHostFragment).
Bottom Navigation con Navigation Component
Una de las integraciones más elegantes: conectar un BottomNavigationView al NavController con una sola línea:
// activity_main.xml — agregás el BottomNavigationView
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_nav_menu" />
// MainActivity.kt — una sola línea conecta todo
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
val navController = findNavController(R.id.navHostFragment)
binding.bottomNav.setupWithNavController(navController)
}
}
Los IDs de los items del menú deben coincidir con los IDs de los Fragments en el NavGraph para que la navegación sea automática.
Control del back stack
A veces necesitás controlar qué pasa con el back stack al navegar:
// Limpiar el back stack al ir a una pantalla (ej: login → home)
findNavController().navigate(
R.id.homeFragment,
null,
NavOptions.Builder()
.setPopUpTo(R.id.loginFragment, inclusive = true)
.build()
)
// Con Safe Args y opciones en el NavGraph (más limpio):
// En nav_graph.xml, en la acción:
<action
android:id="@+id/action_login_to_home"
app:destination="@id/homeFragment"
app:popUpTo="@id/loginFragment"
app:popUpToInclusive="true" />
popUpTo + inclusivepopUpTo le dice a Navigation que limpie el back stack hasta ese destino. Con inclusive=true también lo elimina a él. Útil para flujos de login o para evitar que el usuario vuelva a pantallas intermedias.