Únete a ⁠ #Android11: The Beta Launch Show el 3 de junio.

Cómo diseñar gráficos de navegación

El componente Navigation utiliza un gráfico de navegación para administrar la navegación de tu app. Un gráfico de navegación es un archivo de recursos que contiene todos los destinos de tu app, además de las conexiones lógicas, o acciones, que los usuarios pueden realizar para navegar de un destino al otro. Puedes administrar el gráfico de navegación de tu app con el Editor de Navigation en Android Studio.

Esta sección contiene prácticas recomendadas para diseñar los gráficos de navegación de tu app.

Gráfico de navegación de nivel superior

El gráfico de navegación de nivel superior de tu app debería comenzar con el destino inicial que el usuario ve cuando inicia la app y debería incluir los destinos que ve cuando se desplaza por ella.

Figura 1: Gráfico de navegación de nivel superior.

Gráficos anidados

Por lo general, los flujos de acceso, los asistentes y otros subflujos dentro de tu app se representan mejor como gráficos de navegación anidados. Si anidas flujos de subnavegación autónomos de esta manera, el flujo principal de la IU de tu app es más fácil de comprender y administrar. Además, los gráficos anidados son reutilizables. También proporcionan un nivel de encapsulación, es decir, que los destinos fuera del gráfico anidado no tienen acceso directo a ninguno de los destinos dentro del gráfico anidado. En cambio, deberían navigate() (navegar) al propio gráfico anidado, donde la lógica interna puede cambiar sin afectar el resto del gráfico.

Toma como ejemplo el gráfico de navegación de nivel superior de la Figura 1 e imagina que quieres que el usuario vea las pantallas title_screen y register solo cuando la app se inicia por primera vez. A continuación, se almacena la información del usuario y, en inicios posteriores de la app, deberías dirigir al usuario directamente a la pantalla match. Como práctica recomendada, debes establecer la pantalla match como destino de inicio de un gráfico de navegación de nivel superior y trasladar las pantallas de título y registro a un gráfico anidado, como se muestra en la Figura 2:

Figura 2: Ahora el gráfico de navegación de nivel superior contiene un gráfico anidado.

Cuando se inicia la pantalla de coincidencia, puedes verificar si hay un usuario registrado. Si el usuario no está registrado, puedes dirigirlo a la pantalla de registro. Para obtener más información sobre los casos de navegación condicional, consulta Navegación condicional.

Otra manera de modularizar la estructura de tu gráfico consiste en incluir un gráfico dentro de otro a través de un elemento <include> en el gráfico de navegación superior. De esta manera, el gráfico incluido se puede definir en un módulo o proyecto por separado, lo que maximiza la capacidad de reutilización.

Si tu app depende de módulos de biblioteca, que incluyen un gráfico de navegación, puedes hacer referencia a estos gráficos de navegación mediante un elemento <include>.

Para continuar con el ejemplo del juego de preguntas y respuestas, supongamos que quieres separar las partes de la app que se enfocan en el juego y colocarlas en un módulo de biblioteca por separado a fin de incluir las pantallas in_game, results_winner y game_over en varias apps, como se muestra en el siguiente ejemplo:

<!-- App Module Navigation Graph -->
    <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/match">

       <fragment android:id="@+id/match"
               android:name="com.example.android.navigationsample.Match"
               android:label="fragment_match">

           <!-- Launch into In Game Modules Navigation Graph -->
           <action android:id="@+id/action_match_to_in_game_nav_graph"
               app:destination="@id/in_game_nav_graph" />
       </fragment>

       <include app:graph="@navigation/in_game_navigation" />

    </navigation>
    
<!-- Game Module Navigation Graph -->
    <?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/in_game_nav_graph"
       app:startDestination="@id/in_game">

       <fragment
           android:id="@+id/in_game"
           android:name="com.example.android.gamemodule.InGame"
           android:label="Game">
           <action
               android:id="@+id/action_in_game_to_resultsWinner"
               app:destination="@id/results_winner"  />
           <action
               android:id="@+id/action_in_game_to_gameOver"
               app:destination="@id/game_over"  />
       </fragment>

       <fragment
           android:id="@+id/results_winner"
           android:name="com.example.android.gamemodule.ResultsWinner" >

           <!-- Action back to destination which launched into this in_game_nav_graph-->
           <action android:id="@+id/action_pop_out_of_game"
                               app:popUpTo="@id/in_game_nav_graph" />

       </fragment>

       <fragment
           android:id="@+id/game_over"
           android:name="com.example.android.gamemodule.GameOver"
           android:label="fragment_game_over"
           tools:layout="@layout/fragment_game_over" >

          <!-- Action back to destination which launched into this in_game_nav_graph-->
           <action android:id="@+id/action_pop_out_of_game"
                               app:popUpTo="@id/in_game_nav_graph" />

     </fragment>

    </navigation>
    

Deberías incluir el gráfico de nivel superior en el módulo principal de tu app y tener una referencia de Gradle para todos los módulos que contengan la navegación a la que necesitas hacer referencia.

Acciones generales

Todos los destinos en tu app a los que se pueda llegar a través de más de una ruta deben tener una acción general correspondiente definida para navegar a ese destino. Las acciones generales se pueden usar para navegar a un destino desde cualquier lugar.

Apliquemos este enfoque a nuestro ejemplo del módulo de biblioteca, que tiene la misma acción definida en los destinos de victoria y fin del juego. Debes extraer estas acciones comunes en una sola acción general y hacer referencia a ellas desde los dos destinos, como se muestra en el ejemplo a continuación:

<?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/in_game_nav_graph"
       app:startDestination="@id/in_game">

       <!-- Action back to destination which launched into this in_game_nav_graph-->
       <action android:id="@+id/action_pop_out_of_game"
                           app:popUpTo="@id/in_game_nav_graph"
                           app:popUpToInclusive="true"  />

       <fragment
           android:id="@+id/in_game"
           android:name="com.example.android.gamemodule.InGame"
           android:label="Game">
           <action
               android:id="@+id/action_in_game_to_resultsWinner"
               app:destination="@id/results_winner"  />
           <action
               android:id="@+id/action_in_game_to_gameOver"
               app:destination="@id/game_over"  />
       </fragment>

       <fragment
           android:id="@+id/results_winner"
           android:name="com.example.android.gamemodule.ResultsWinner" />

       <fragment
           android:id="@+id/game_over"
           android:name="com.example.android.gamemodule.GameOver"
           android:label="fragment_game_over"
           tools:layout="@layout/fragment_game_over" />

    </navigation>
    

Consulta Acciones generales en los documentos de navegación para obtener más información y ejemplos sobre cómo usar acciones generales en tus fragmentos.