Como usar Navigation Graph | Android Studio| Kotlin

Guía rápida para navegar

Alejandro Torres
6 min readAug 22, 2023

Hola, me quiero tomar el tiempo de compartir este pequeño conocimiento para Android Studio ya que siento que no hay mucha información al respecto, cabe destacar que esto tiene documentación oficial, lo que intento es explicar como me gustaría que me lo hubiesen explicado, vamos a ver los siguientes temas:

  • Crear nuevo proyecto en Android Studio
  • Agregar dependencias necesarias.
  • Explicación rápida del Navigation Graph.
  • Como navegar de un destino de tu app a otro.

Por otra parte decir que se necesita un conocimiento básico de Android Studio para entender algunas cosas, de igual manera voy a ir explicando de una manera suave con ejemplos.

¡Empecemos!

Creamos un nuevo proyecto

Abrimos Android Studio hacemos clic en New > New Project > Basic Views Activity

Como nombre le vamos a poner: Curso Navigation Graph, hacemos clic en Finish.

Figura 1. Ejemplo de como crear el proyecto nuevo

Vistas para el ejemplo

Al haber seguido los pasos anteriores Android Studio va a crear los siguientes archivos que vamos a necesitar para esta corta clase:

Dentro de tu package:

  • FirstFragment.kt
  • MainActivity.kt
  • MainFragment.kt
  • SecondFragment.kt

Dentro de la carpeta res/layout:

  • activity_main.xml
  • content_main.xml — este lo vamos a borrar y vamos a crear un archivo llamado: fragment_main.xml, mas adelante te explico como hacerlo.
  • fragment_first.xml
  • fragment_second.xml

Dentro de la carpeta res/navigation/

  • nav_graph.xml

Vamos a editar un poco los archivos, copia y pega el contenido en cada uno de los archivos.

Contenido del 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>

Vamos a crear un fragmento nuevo llamado fragment_main.xml:

Seguimos estos pasos:

  • Clic derecho en tu package java — New — Fragment — Blank.
  • Aparece un popup y le colocamos el siguiente nombre: MainFragment y al layout le colocamos fragment_main.xml.
  • ¡Clic en finish y listo!
Figura 2. Ejemplo de como crear el fragmento

Contenido del archivo fragment_main.xml:

<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<Button
android:id="@+id/go_to_first_fragment"
android:text="@string/ir_al_primer_fragmento"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/go_to_second_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ir_al_segundo_fragmento"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/go_to_first_fragment"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>

Contenido del fragment_first.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstFragment">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">

<Button
android:id="@+id/back_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/back"
app:layout_constraintBottom_toTopOf="@id/textview_first"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/textview_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/lorem_ipsum"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/back_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

Contenido del fragment_second.xml:

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">

<Button
android:id="@+id/back_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/back"
app:layout_constraintBottom_toTopOf="@id/textview_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/lorem_ipsum"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/back_button" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

Ahora vamos con los archivos Kotlin:

NOTA IMPORTANTE: si estas copiando y pegando ten en cuenta que el nombre de tu package puede ser distinto al que usamos para esta clase asi que reemplaza com.aletorres.cursonavigationgraph por el nombre de tu package.

MainActivity.kt: es la actividad principal que nos proporciona una pantalla en la cual el usuario va a interactuar, contenido:

package com.aletorres.cursonavigationgraph

import android.os.Bundle
import com.google.android.material.snackbar.Snackbar
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.navigateUp
import androidx.navigation.ui.setupActionBarWithNavController
import android.view.Menu
import android.view.MenuItem
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import com.aletorres.cursonavigationgraph.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)

binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
}
}

MainFragment.kt: este archivo va asociado con el archivo fragment_main.xml, fue el archivo que creamos en uno de los pasos anteriores, su contenido:

package com.aletorres.cursonavigationgraph

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.aletorres.cursonavigationgraph.databinding.FragmentMainBinding

class MainFragment : Fragment() {
private lateinit var binding: FragmentMainBinding

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMainBinding.inflate(inflater, container, false)
binding.goToFirstFragment.setOnClickListener{
findNavController().navigate(R.id.action_mainFragment_to_firstFragment) // This function makes possible the navigation
}
binding.goToSecondFragment.setOnClickListener {
findNavController().navigate(R.id.action_mainFragment_to_secondFragment) // This function makes possible the navigation
}
return binding.root
}
}

FirstFragment.kt: este archivo va asociado con el archivo fragment_first.xml, contenido:

package com.aletorres.cursonavigationgraph

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.aletorres.cursonavigationgraph.databinding.FragmentFirstBinding

class FirstFragment : Fragment() {

private lateinit var binding: FragmentFirstBinding

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentFirstBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.backButton.setOnClickListener {
findNavController().navigate(R.id.action_firstFragment_to_mainFragment) // This function makes possible the navigation
}
}
}

SecondFragment.kt: este archivo va asociado con el archivo fragment_second.xml, contenido:

package com.aletorres.cursonavigationgraph

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.navigation.fragment.findNavController
import com.aletorres.cursonavigationgraph.databinding.FragmentSecondBinding

class SecondFragment : Fragment() {

private lateinit var binding: FragmentSecondBinding

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {

binding = FragmentSecondBinding.inflate(inflater, container, false)
return binding.root
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

binding.backButton.setOnClickListener {
findNavController().navigate(R.id.action_secondFragment_to_mainFragment) // This function makes possible the navigation
}
}
}

Con eso tenemos por ahora, vamos al siguiente paso.

Configurando tu entorno

Por favor vamos a incluir este componente dentro de tu app si ya no lo tenias antes, así que vamos a copiar en el archivo app/build.gradle el siguiente código:

dependencies {
implementation 'androidx.core:core-ktx:1.8.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.6.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.6.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

def nav_version = "2.5.3"

// Java language implementation
implementation "androidx.navigation:navigation-fragment:$nav_version"
implementation "androidx.navigation:navigation-ui:$nav_version"

// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"

// Feature module Support
implementation "androidx.navigation:navigation-dynamic-features-fragment:$nav_version"

// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"

// Jetpack Compose Integration
implementation "androidx.navigation:navigation-compose:$nav_version"
}

De esta manera nos aseguramos que tenemos las dependencias necesarias.

Figura 3. Ejemplo de como debe quedar nuestro archivo build.gradle

NOTA IMPORTANTE: Recuerda sincronizar dependencias del proyecto luego de esto.

Navigation Graph

La navegación ocurre entre los destinos de tu app, estos destinos están conectados por acciones.

Un Navigation Graph es un archivo que contiene tus destinos y acciones.

Un poco de teoría antes no cae mal:

¿Qué es un destino?

Son diferentes vistas de tu app, por ejemplo un fragmento que tenga tu lógica de iniciar sesión en tu app.

¿Qué es una acción?

Son conexiones lógicas entre tus destinos, representa el camino que los usuarios pueden tomar en tu app.

Figura 4. Ejemplo de Navigation Graph que muestra vistas previas de seis destinos diferentes que están conectados a través de cinco acciones.

Edición del Navigation Graph

Al haber creado el proyecto con la plantilla basic views activity se creo un archivo llamado: nav_graph el cual esta ubicado en la carpeta res/navigation.

Vamos al archivo nav_graph.xml doble clic en el y luego se debería ver la pantalla del Navigation Graph, haz clic en New Destination, luego de eso selecciona los fragmentos uno por uno:

  • MainFragment
  • FirstFragment
  • SecondFragment

Sigamos este ejemplo gráfico para crear nuestros destinos y acciones:

Figura 5. Ejemplo de como crear las acciones en Android Studio

Ahora el paso final vamos a ver el resultado de haber seguido todos estos pasos y ejecutamos nuestra aplicación usando Android Studio.

El resultado

Bien, es probable que en algún paso nos hayamos equivocado ( a mi me pasa algunas veces jeje ), pero por si acaso te voy a dejar un repositorio donde podrás encontrar todo el código fuente para esta clase de ejemplo:

https://github.com/IIalejoII/android-como-usar-navigation-graph

Figura 6. Probando la aplicación

Muchas gracias por tu tiempo.

Pronto pienso subir esta misma clase en video a Youtube.

Video de Youtube

Mi canal: @aletorres1102

--

--