En este tutorial te mostraremos los pasos para implementar el Navigation Component en tus Apps Android. Así tendrás una arquitectura de navegación basada en fragmentos.
1. Crea Un Proyecto Nuevo
Entra a Android Studio y crea un nuevo proyecto Kotlin llamado «Navigation Component».
Usa como plantilla una Empty Activity para que te sirva como la actividad de punto de entrada.
Omite este paso si vas a usar un proyecto existente, donde deseas añadir el componente.
2. Añadir Dependencias Del Navigation Component
Abre tú archivo build.gradle
a nivel de proyecto y escribe una variable para la versión actual del navigation component:
ext{
nav_version = "2.3.2"
}
Ahora ve a build.gradle
del módulo y añade las siguientes dependencias para los componentes de navegación:
dependencies {
/*...*/
// Navegación
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
/*...*/
}
Luego sincroniza tu proyecto para incorporar los paquetes.
3. Crear Gráfico De Navegación
Como siguiente paso, añade el navigation graph a los recursos de tu proyecto.
Haz click derecho en la carpeta res
y seleccionar New|Android Resource File.
Cuando se despliegue el diálogo de creación, usa para File Name el nombre «nav_graph» y elige la entrada Navigation en Resource Type. Confirma la creación con OK.
Luego podrás ver al archivo en el directorio res/navigation
.
4. Crear NavHostFragment
Recordemos que NavHostFragment
provee un área dentro de tu layout, en donde ocurrirá la navegación.
Para su creación, abre el layout creado por defecto por Android Studio llamado activity_main.xml
.
Crea una etiqueta <FragmentContainerView>
en su interior y define los siguientes tres atributos relacionados a la navegación:
android:name
— UsaNavHostFragment
como clase de creaciónapp:navGraph
— Vincula al recursonav_graph.xml
app:defaultNavHost
— Usa true para otorga el control del botón «Atrás» del sistema a esteNavHostFragment
.
El código final sería este:
<?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"
tools:context=".MainActivity">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
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>
5. Añadir Fragmentos Al Gráfico De Navegación
Para este ejemplo vamos a crear tres fragmentos para simular:
- Una pantalla de lista
- Un pantalla de detalle
- Una pantalla de creación y edición.
Cada uno de estos elementos representará un destino (destination) de la navegación.
Abre nav_graph.xml
para visualizar el editor de navegación. Si no lo ves, presiona la pestaña Split o Design del recurso.
Crea el primer fragmento de lista, presionando el botón New Destination y luego Create new destination:
Estas acciones desplegaran un diálogo para crear fragmentos, donde seleccionarás el tipo de plantilla que requieras. En este ejemplo usaremos Fragment (Blank) por simplicidad.
Nombra al primer fragmento como «ExampleListFragment» y confirma su creación. Verás que en el editor de navegación este se reflejará como el primer destino.
Ahora, repite el mismo proceso con los destinos de detalle y creación/edición hasta que tu editor se vea así:
6. Elegir Destino Inicial
En este momento ExampleListFragment
es el destino inicial, lo cual es lo que deseamos.
Pero si deseas modificarlo, haz click derecho en el destino y luego selecciona Set as Start Destination:
Esto es equivalente a modificar el atributo app:startDestination
del elemento <navigation>
en nav_graph.xml
. Usa el id del fragmento que deseas establecer como inicio.
<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"
android:id="@+id/nav_graph"
app:startDestination="@id/exampleListFragment">
<!-- ... ->
</navigation>
7. Conectar Destinos
La conexión entre dos destinos es representada por una Acción en el editor o <action>
en el código.
Para conectar dos destinos en el editor, sitúate en el destino de origen y arrastra el circulo emergente en su borde hacia el destino final.
Para nuestro ejemplo necesitaremos las siguientes conexiones:
- De Lista a detalle
- De detalle a edición
- De Lista a creación
Al generar las acciones deberías ver lo siguiente en el editor:
Si cambias a la pestaña Code tendrás la siguiente definición XML:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav_graph"
app:startDestination="@id/exampleListFragment">
<fragment
android:id="@+id/exampleListFragment"
android:name="com.develou.navigationcomponent.ExampleListFragment"
android:label="fragment_example_list"
tools:layout="@layout/fragment_example_list" >
<action
android:id="@+id/action_exampleListFragment_to_exampleDetailFragment3"
app:destination="@id/exampleDetailFragment" />
<action
android:id="@+id/action_exampleListFragment_to_exampleAddEditFragment"
app:destination="@id/exampleAddEditFragment" />
</fragment>
<fragment
android:id="@+id/exampleDetailFragment"
android:name="com.develou.navigationcomponent.ExampleDetailFragment"
android:label="fragment_example_detail"
tools:layout="@layout/fragment_example_detail" >
<action
android:id="@+id/action_exampleDetailFragment_to_exampleAddEditFragment2"
app:destination="@id/exampleAddEditFragment" />
</fragment>
<fragment
android:id="@+id/exampleAddEditFragment"
android:name="com.develou.navigationcomponent.ExampleAddEditFragment"
android:label="fragment_example_add_edit"
tools:layout="@layout/fragment_example_add_edit" />
</navigation>
Para mejorar la legibilidad de los ids de las acciones, refactorizalos a:
action_list_to_detail
action_list_to_add
action_detail_to_edit
8. Navegar Hacia Un Destino
El elemento encargado de realizar la navegación entre fragmentos es el NavController
. Este recibe la acción generada en el editor de navegación para iniciar al destino establecido.
Navegar De Lista A Detalle
Para iniciar la navegación necesitamos controles de interfaz que permitan desencadenar las acciones.
Modifica el layout de ExampleListFragment
para que posea dos botones. Uno para ir hacia el detalle y otro para la creación.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".ExampleListFragment">
<Button
android:id="@+id/detail_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="DETALLE" />
<Button
android:id="@+id/create_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CREAR" />
</LinearLayout>
Con los botones en el layout, ahora ve a ExampleListFragment.kt
y:
- Obtén las referencias de los botones
- Asignales una escucha de click
- Encuentra al
NavController
conView.findNavController()
- Usa el método
navigate()
, pasando como parámetro el id de las acciones de navegación
El fragmento de lista tendría este código al aplicar las acciones anteriores:
class ExampleListFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflar layout
val root = inflater.inflate(R.layout.fragment_example_list, container, false)
setupNavigation(root)
return root
}
private fun setupNavigation(root: View) {
val detailButton = root.findViewById<Button>(R.id.detail_button)
val createButton = root.findViewById<Button>(R.id.create_button)
detailButton.setOnClickListener { view: View ->
view.findNavController().navigate(R.id.action_list_to_detail)
}
createButton.setOnClickListener { view: View ->
view.findNavController().navigate(R.id.action_list_to_add)
}
}
}
Repite este proceso para ExampleDetailFragment
. Añádele un botón que vaya hacia la edición y llama a navigate()
en el evento de click.
9. Añadir Up Button En La App Bar
Lo siguiente es añadir el Up Button en la barra de acción.
Abre MainActivity
, ve a onCreate()
y obtén la referencia del NavHostFragment
.
Luego llama método NavigationUI.setupActionBarWithNavController()
para que la App Bar sea usada por NavContoller
:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
NavigationUI.setupActionBarWithNavController(this, navHostFragment.navController)
}
Luego sobrescribe onSupportNavigateUp()
para transferir la responsabilidad del evento del Up Button al NavController
.
Esto se logra llamando a NavController.navigateUp()
:
override fun onSupportNavigateUp(): Boolean {
val navController = this.findNavController(R.id.nav_host_fragment)
return navController.navigateUp()
}
Modificar Título De App Bar
Si corres la aplicación en el estado actual verás los labels autogenerados en el título de la App Bar. Esto se debe a que el NavController
toma el atibuto android:label
de los fragmentos de nav_graph.xml
.
Evidentemente, tener los títulos correctos consiste en usar los labels correctos. Por lo que es solo cuestión de modificarlos:
Por ejemplo, al fragmento para la creación/edición puedes ponerle ese mismo título:
<fragment
android:id="@+id/exampleAddEditFragment"
android:name="com.develou.navigationcomponent.ExampleAddEditFragment"
android:label="Creación/Edición"
tools:layout="@layout/fragment_example_add_edit" />
Nota: Reemplaza los strings escritos directamente por recursos.
10. Correr Aplicación Android
Finalmente ejecuta el proyecto y navega entre los diferentes destinos:
Puedes descargar el código desde el siguiente enlace: