¿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")
}

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>

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.

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.