BasicNavigationDrawer – AndroidX

En esta entrada vamos a construir una aplicación basada en el Navigation Drawer actualizada a la versión de liberías de AndroidX. La vamos a hacer desde cero, es decir, desde una aplicación en blanco.

El componente Navigation

Referencia -> Android Developers (Navigation)

El componente Navigation consta de tres partes clave que se describen a continuación:

  • Gráfico de navegación: Es un recurso XML que contiene toda la información relacionada con la navegación en una ubicación centralizada.
    Esto incluye todas las áreas de contenido individuales dentro de tu app, llamadas destinos, así como las posibles rutas que un usuario puede tomar a través de tu app.
  • NavHost: Es un contenedor vacío que muestra los destinos de tu gráfico de navegación.
    El componente Navigation contiene una implementación NavHost predeterminada, NavHostFragment, que muestra destinos de fragmentos.
  • NavController: Es un objeto que administra la navegación de la app dentro de un NavHost.
    NavController orquesta el intercambio de contenido de destino en el objeto NavHost a medida que los usuarios se mueven a través de tu app.

Mientras navegas por tu app, le dices a NavController que quieres navegar por una ruta específica de tu gráfico de navegación o directamente a un destino específico. Luego, NavController muestra el destino apropiado en NavHost.

El componente Navigation ofrece algunas otras ventajas, entre las que se incluyen las siguientes:

  • Administrar transacciones de fragmentos
  • Administrar correctamente las acciones predeterminadas Arriba y Atrás
  • Proporcionar recursos estandarizados para animaciones y transiciones
  • Implementar y administrar vínculos directos
  • Incluir patrones de IU de Navigation, como paneles laterales de navegación y navegación inferior, con un mínimo de esfuerzo adicional
  • Safe Args, un complemento de Gradle que proporciona seguridad de tipo al navegar y pasar datos entre destinos
  • Compatibilidad con ViewModel, que te permite incluir un ViewModel en un gráfico de navegación para compartir datos relacionados con la IU entre los destinos del gráfico
  • Además, puedes utilizar Navigation Editor de Android Studio para ver y editar tus gráficos de navegación.

Principios de Navegación

Leer el artículo Principios de Navegación de Android Developers

Proyecto

Vamos a crear un proyecto como el de la imagen animada.

Un Drawer que se desplaza sobre la pantalla inicial que tiene un menu con distintas opciones que actualizan el Fragment de destino.

Utilizaremos el Componente Navigation de AndroidX, crearemos un Toolbar donde instanciaremos el menú de Hamburguesa y la Flecha atrás.

Los pasos Steps a seguir serán los siguientes.

  • Proyecto
    Creamos el proyecto inicial e importamos las dependencias necesarias
  • Media
    Cargamos las imagenes en el proyecto
  • Fragments
    Creamos cada uno de los Fragments y editamos su contenido
  • Menú de Navegación
    Creamos el menú lateral con sus iconos y los identificadores correctos
  • Header de Navegación
    Creamos la cabecera que ilustra el menú de navegación
  • Navigation Graph
    Creamos el Navigation Graph necesario para gestionar la navegación
  • Activity Main y NavHost
    Modificamos el Layout de la activity main para componerla con todo lo anterior
  • Funcionalidad
    Asignamos la funcionalidad a los distintos componentes
    • Instanciamos el Toolbar
    • Instanciamos el NavController
    • Configuramos la Application Bar
    • Instanciamos el Navigation Menu

Step 1Creación del proyecto inicial

Lo primero que tenemos que hacer es crear un nuevo proyecto basado en EmptyActivity.

Una vez, creado tenemos que añadir un par de dependencias a librerías necesarias para trabajar con el Navigation Drawer con la nueva versión.

Si nos fijamos en la imagen, vemos que en dependencias seleccionamos + (añadir), seleccionamos Add Library Dependency, lo que nos saca la pantalla de la derecha de la imagen, en ella, utilizamos el buscador, buscamos androidX.navigation y pulsamos Search como estamos en Java, selecionamos las Artifact Name que no tengan -ktx (de kotlin).

Hay que ir añadiendo una a una. Son las que se muestran en la imagen:

Step 2 – Recursos

Copiando recursos

Descargar los recursos de esta aplicación, o bien si habéis clonado la aplicación de GitHub tenéis un directorio con los recursos en el raiz de la aplicación.

Arrastramos los iconos, desde la carpeta del explorador de archivos a la carpeta mipmap manteniendo pulsada la tecla CTRL como se muestra en la imagen.

Esto crea los recursos en el proyecto.

Ahora volvemos al menú y elegimos el recurso mipmap para cada item del menú.

Step 3 – Fragments

Cada elmento del menú nos llevará a un Fragment que se hospedará en nav_host_fragment que añadiremos cuando modifiquemos la Main Activity

Además de los fragments del menú, añadiremos un Fragment de Wellcome para que sea el inicial antes de que el usuario seleccione un elemento del menú.

Crear Fragments

Para crear un fragment vamos al menu File->New->Fragment->Fragment(Blank)

Sustituimos el nombre BlankFragment por WellcomeFragment y pulsamos finish.

Esto nos crea la clase Java para el Fragment y el xml layout.

En el layout, convertivos el Framelayout que genera como root del layout por un Constraint Layout. Se hace con botón derecho sobre el Framelayout en la vista de Tree del editor y seleccionando el menú Convet to …

Repetimos esto para los demás fragments: GuisosFragment, PastasFragment, FritosFragment, SopasFragment, PostresFragments y Preferencias (El de Email no los creamos veremos en otra ocasión como darle uso)

Creamos los fragments como vienen en la imagen animada, con su icono y una descripción central.

Fragment de bienvenida o inicial

Cuando arranca la aplicación, el primer fragment que se va a colocar será este. Será el fragment que añadiremos primero al NavigationGraph y por tanto tendrá la propiedad de ser el Start Destination.

Creamos el fragment como los demás pero le añadimos la imagen jpg con los platos y en la parte superior colocarmos un TextView con un índice Z superior al de la imagen para que se vea por encima en color blanco.

Tal como se muestra en la imagen.

Para que el TextView se ponga en una capa superior y no quede oculto por la imagen utilizamos la propiedad android:translationZ y le ponemos valor 1dp

Step 4 – Menú de Navegación

Estructura del menú y su apariencia en el NavigationView

Pulsamos el botón derecho del ratón en carptea de res (resources), seleccionamos New->Android Resource File

De nombre ponemos nav_menu y de tipo Menu

Esto nos crea el recurso menu en la carpeta apropiada y nos lleva al editor de menús.

Arrastramos elementos Menú Items y Menus debajo de menú en el orden apropiado, las propiedades que modificamos de momento son id y title.

Para que el componente Navigation gestione adecuadamente la navegación desde el menú tenemos que poner como id el mismo id que tenemos puesto o que pondremos en el Navigation Graph para cada uno de los destinos. Por tanto como id ponemos guisos_dest, fritos_dest, etc… y el title correspondiente. Recordar luego en el Navigation Graph de poner el mismo id a los destinos.

En la imagen vemos como queda la estructura del menú, la representación visual en el editor de menus no es como quedará, se muestra también como queda el menú una vez montado el NavigationView.

Los items que ponemos como etiquetas (Comidas Caseras y Opciones) deben marcarse con el atributo showAsAction:Never

Para cada elemento del menú buscamos su imagen y la colocamos en el atributo icon

Como vemos en el código y en la imagen hemos puesto dos items a modo de categoría y debajo de ellos cuelga un submenú con las opciones.

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/miCarta"
        android:title="Comidas Caseras"
        app:showAsAction="never">
        <menu>
            <item
                android:id="@+id/guisos_dest"
                android:icon="@mipmap/ic_guisos"
                android:title="Guisos" />
            <item
                android:id="@+id/pastas_dest"
                android:icon="@mipmap/ic_pasta"
                android:title="Pastas" />
            <item
                android:id="@+id/fritos_dest"
                android:icon="@mipmap/ic_fritos"
                android:title="Fritos" />
            <item
                android:id="@+id/sopas_dest"
                android:icon="@mipmap/ic_sopas"
                android:title="Sopas" />
            <item
                android:id="@+id/postres_dest"
                android:icon="@mipmap/ic_postres"
                android:title="Postres" />
        </menu>
    </item>
    <item
        android:id="@+id/miOpciones"
        android:title="Opciones"
        app:showAsAction="never">
        <menu>
            <item
                android:id="@+id/preferencias_dest"
                android:icon="@android:drawable/ic_menu_preferences"
                android:title="Preferencias" />
            <item
                android:id="@+id/mail_dest"
                android:icon="@android:drawable/ic_dialog_email"
                android:title="Mail" />
        </menu>
    </item>
</menu>

Step 5 – Header para el Navigation View

Como vemos en la imagen desplegada del Navigation View como cabecera tiene una imagen jpg con los platos. Esta imagen la añadimos a un layout y colocaremos el layout en el atributo app:headerLayout del NavigationView cuando construyamos el ActivityMain en el Step 7.

Creamos un nuevo Resource File seleccionando el tipo layout, le llamamos header.xml, añadimos un image view con las propiedades necesarias para que aparezca arriba y con el tamaño apropiado. El ImageView tiene un tamaño que tenemos que hacer coincidir exactamente con el de la imagen para que no se vean margenes blancos arriba y abajo (puesto que la imagen es más ancha que alta). Esto podemos hacerlo jugando con las propiedades width y heigth del ImageView o podemos usar la propiedad android:adjustViewBounds que hace que el ImageView se ajuste al tamaño de la imagen. Ponemos width y heigth a Wrap Content.

<?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="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imageView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.0"
        app:srcCompat="@drawable/header" />
</androidx.constraintlayout.widget.ConstraintLayout>

Con esto ya tenemos el layout construido, luego lo añadiremos al NavigationView cuando creemos la MainActivity.

Step 6 – Navigation Graph

Ahora ya estamos en condiciones de crear el Navigation Graph, ya tenemos los Fragments que servirán de destino en el mismo. Vamos a crearlo y luego en el siguiente paso lo añadiremos a la propiedad correcta en el FragmentContainerView que identificaremos como nav_host_fragment.

Creamos un Resource File de tipo Navigation y lo identificamos como nav_graph con lo que generamos el fichero nav_graph.xml bajo la carpeta navigation en resources.

Añadimos el primer fragmen al Navigation Graph, el fragment de bienvenida que definimos antes. Este será el Start Destination.

Para el componente navegación los fragments que añadimos se denominan destinations. Identificaremos los destinations con el sufijo _dest para que sepamos que es un destino en el NavigationGraph. Vamos a identificar el fragment incial por tanto como wellcome_dest. En el menú no tenemos este fragment porque no hay ninguna opción de menú que nos lleve a el, pero podríamos haberla puesto (Home por ejemplo).

Asignamos la propiedad label como Wellcome a este fragment. La propiedad label será el texto que se muestre en el Toolbar superior.

Repetimos para todos los fragments, añadimos uno a uno y les colocamos su identificación y su label apropiadamente.

Cuando estén todos creamos una Acción desde el Wellcome destination a cada uno de los destinations que hemos añadido. Esta acción por defecto será la que utilice el NavControler para navegar de un destino a otro cuando un menú se llame (id) igual que el destination (id).

El Navigation Graph tendrá el aspecto de la imagen y su código será el siguiente.

<?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/wellcome_dest">

    <fragment
        android:id="@+id/wellcome_dest"
        android:name="com.amm.navigationdrawer.WellcomeFragment"
        android:label="Wellcome"
        tools:layout="@layout/fragment_wellcome">
        <action
            android:id="@+id/action_wellcome_dest_to_guisosFragment"
            app:destination="@id/guisos_dest" />
        <action
            android:id="@+id/action_wellcome_dest_to_pastasFragment"
            app:destination="@id/pastas_dest" />
        <action
            android:id="@+id/action_wellcome_dest_to_fritosFragment"
            app:destination="@id/fritos_dest" />
        <action
            android:id="@+id/action_wellcome_dest_to_sopasFragment"
            app:destination="@id/sopas_dest" />
        <action
            android:id="@+id/action_wellcome_dest_to_postresFragment"
            app:destination="@id/postres_dest" />
        <action
            android:id="@+id/preferencias_dest"
            app:destination="@id/preferencias_dest" />
    </fragment>
    <fragment
        android:id="@+id/guisos_dest"
        android:name="com.amm.navigationdrawer.GuisosFragment"
        android:label="Guisos"
        tools:layout="@layout/fragment_guisos" />
    <fragment
        android:id="@+id/pastas_dest"
        android:name="com.amm.navigationdrawer.PastasFragment"
        android:label="Pastas"
        tools:layout="@layout/fragment_pastas" />
    <fragment
        android:id="@+id/fritos_dest"
        android:name="com.amm.navigationdrawer.FritosFragment"
        android:label="Fritos"
        tools:layout="@layout/fragment_fritos" />
    <fragment
        android:id="@+id/sopas_dest"
        android:name="com.amm.navigationdrawer.SopasFragment"
        android:label="Sopas"
        tools:layout="@layout/fragment_sopas" />
    <fragment
        android:id="@+id/postres_dest"
        android:name="com.amm.navigationdrawer.PostresFragment"
        android:label="Postres"
        tools:layout="@layout/fragment_postres" />
    <fragment
        android:id="@+id/preferencias_dest"
        android:name="com.amm.navigationdrawer.PreferenciasFragment"
        android:label="Preferencias"
        tools:layout="@layout/fragment_preferencias" />
</navigation>

Step 7 – Main Activity, NavHost

Ya estamos en condiciones de modificar el activity_main.xml que nos genera Android Studio para un proyecto vacío. No lo hemos hecho lo primero porque teníamos los elementos que nos hacían falta.

Necesitamos un DrawerLayout como raiz de nuestro activity_main.xml. Pero no está en la paleta grafica de herramientas, así que lo ponemos desde la vista de código:

La paleta de herramientas del editor de layouts, solo muestra vistas monocapa estáticas, mientras que DrawerLayout es un ViewGroup complicado y tiene varias capas: el cajón (drawer) y el contenido (content).

androidx.drawerlayout.widget.DrawerLayout

Para cambiar el ConstraintLayout que viene por defecto en el activity_main.xml y poner el drawerlayout en su lugar como raiz de nuestro layout:

Tenemos que seleccionar el texto androidx.constraintlayout.widget.ConstraintLayout (no coger el < inicial) y empezamos a escribir drawerlayout con lo que nos aparece ya el componente a seleccionar, lo seleccionamos y pulsamos intro.

Tenemos que construir el arbol que vemos enla imagen, un LinearLayout vertical que incluye el Toolbar y el FragmentContainerView que son componentes que encontramos en la paleta bajo Containers. Luego viene un NavigationView debajo del LinearLayout (también lo encontramos en Containers). Arrastramos los elementos y los posicionamos como se ve en la imagen.

Las identificaciones serán:

  • DrawerLayout –> android:id=”@+id/drawer_layout
  • Toolbar –> android:id=”@+id/toolbar
  • FragmentContainerView –> android:id=”@+id/nav_host_fragment
  • NavigationView –> android:id=”@+id/nav_view

Al FragmentContaierView, nuestro nav_host_fragment debemos añadirle estas dos propiedades

app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"

para que sea el componente Host para los fragments y para asignarle cual es el Navigation Graph del que leer los fragments (destinations) a colocar en ese hueco.

En el NavitagionView debemos colocar las siguientes propiedades

android:layout_gravity="start"
app:headerLayout="@layout/header"
app:menu="@menu/nav_menu" />

Layout_gravity=start hace que el Layout del NavigationView se coloque a la izquierda, fuera del campo de la pantalla y que se pueda desplazar hacia la derecha con el dedo.
HeaderLayout coloca nuestro header layout (header.xml) como cabecera en la parte superior del Navigation View.
Menu indica cual es el menú que debe dibujar en el Navigation View

El código del activity_main.xml queda tras esto así

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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"
    android:id="@+id/drawer_layout"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            android:minHeight="?attr/actionBarSize"
            android:theme="?attr/actionBarTheme"
            app:titleTextColor="@color/white" />

        <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:navGraph="@navigation/nav_graph" />
    </LinearLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/header"
        app:menu="@menu/nav_menu" />
</androidx.drawerlayout.widget.DrawerLayout>

Step 8 – Instanciando el Toolbar

Ya hemos terminado con la parte gráfica, ahora comenzamos con el código Java para dotar de funcionamiento correcto.

Este y los siguients Steps vamos a trabajar con el código del ActivityMain básicamente. Los fragments no tienen código en este tutorial.

En el paso anterior hemos arrastrado un Toolbar desde la paleta de compoentes al layout del activity_main, por lo que vamos a utilizar un Toolbar propio que hemos identficado como toolbar. Por tanto tenemos que utilizar un tema (Android Theme) que no tenga incorporado el Toolbar, puesto que lo vamos a gestionar nosotros.

Para seleccionar un Theme sin ActionBar debemos hacer que nuestra App herede de uno que no tenga Toolbar.

En la carpeta de recursos, subcarpeta themes vemos el fichero themes.xml que es donde se asocia el tema para nuestra app. Como parent de nuestro tema pone Theme.MaterialComponents.DayNight.DarkActionBar. Borrando .DarkActionBar y poniendo de nuevo el punto (.) el editor nos ofrece demas de la misma familia, elegimos el NoActionBar

<style name="Theme.NavigationDrawer" parent="Theme.MaterialComponents.DayNight.NoActionBar">

Ahora vamos al código java para MainActivity y en el onCreate() instanciamos el toolbar y lo asignamos con setSupportActionBar()

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

Step 9 – Instanciando el NavController

El Controlador de navegación es un objeto que posee el nav_host_fragment, nuestro androidx.fragment.app.FragmentContainerView en el layout.

Por tanto primero tenemos que instanciar ese fragment como NavHostFragment y de él obtener el NavController, las siguientes lineas a añadir en el onCreate() hacen eso.

        NavHostFragment host = (NavHostFragment) getSupportFragmentManager()
                .findFragmentById(R.id.nav_host_fragment);

        // Set up Action Bar
        NavController navController = host.getNavController();

Step 10 – Configurando el Application Bar

Para este paso necesitamos declarar estos dos objetos a nivel de clase en la MainActivity

    private DrawerLayout drawerLayout;
    private AppBarConfiguration appBarConfiguration;

Ahora en el onCreate() instanciamos el drawerLayout con findViewById buscando el id que le dimos al elemento raiz del activity_main.xml (drawer_layout)

Revisar el Step 11 de Android Navigation – Java donde se explica los fundamentos de la appBarConfiguration.

Aquí añadimos al Set<Int> todos los elementos del menú excepto Preferencias porque queremos que ésta muestre la flecha atrás en vez del menú Hamburguesa.

        drawerLayout = findViewById(R.id.drawer_layout);

        Set<Integer> topLevelDestinations = new HashSet<>();
        topLevelDestinations.add(R.id.wellcome_dest);
        topLevelDestinations.add(R.id.guisos_dest);
        topLevelDestinations.add(R.id.fritos_dest);
        topLevelDestinations.add(R.id.pastas_dest);
        topLevelDestinations.add(R.id.sopas_dest);
        topLevelDestinations.add(R.id.postres_dest);

        if (null != drawerLayout) {
            appBarConfiguration = new AppBarConfiguration.Builder(topLevelDestinations)
                    .setOpenableLayout(drawerLayout)
                    .build();
        }
        else {
            appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
        }

        setupActionBar(navController, appBarConfiguration);

La última línea llama a la función setupActionBar(navController, appBarConfiguration) que tenemos que declarar (es la misma función que el step12 del tutorial de Android Navigation – Java

private void setupActionBar(NavController navController,
AppBarConfiguration appBarConfig) {
//TODO STEP 12 - Have NavigationUI handle what your ActionBar displays
// This allows NavigationUI to decide what label to show in the action bar
// By using appBarConfig, it will also determine whether to
// show the up arrow or drawer menu icon
NavigationUI.setupActionBarWithNavController(this, navController,appBarConfiguration);
//END STEP 12
}

Además tenemos que añadir el Callback que android llama para proporcionar el funcionamiento de la flecha atrás del AppBar y el Hamburguer Menú, corresponde al Step 12 del tutorial de Android Navigation – Java

    //TODO STEP 12  - Have NavigationUI handle up behavior in the ActionBar
    @Override
    public boolean onSupportNavigateUp() {
        // Allows NavigationUI to support proper up navigation or the drawer layout
        // drawer menu, depending on the situation
        return NavigationUI.navigateUp(Navigation.findNavController(this, R.id.nav_host_fragment), appBarConfiguration);
    }
    //END STEP 12

Para que el color del Hamburguer menú y la flecha atrás sean blancas, lo que hacemos es modificar el Theme de nuevo, el themes.xml queda así, se ha añadido el estilo final y su llamada en el estilo que ya había

<resources xmlns:tools="http://schemas.android.com/tools">
    <!-- Base application theme. -->
    <style name="Theme.NavigationDrawer" parent="Theme.MaterialComponents.DayNight.NoActionBar">
        <!-- Primary brand color. -->
        <item name="colorPrimary">@color/purple_500</item>
        <item name="colorPrimaryVariant">@color/purple_700</item>
        <item name="colorOnPrimary">@color/white</item>
        <!-- Secondary brand color. -->
        <item name="colorSecondary">@color/teal_200</item>
        <item name="colorSecondaryVariant">@color/teal_700</item>
        <item name="colorOnSecondary">@color/black</item>
        <!-- Status bar color. -->
        <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
        <!-- Customize your theme here. -->
        <!-- https://stackoverflow.com/a/49252342 -->
        <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
    </style>
    <style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
        <item name="spinBars">true</item>
        <item name="color">@android:color/white</item>
    </style>
</resources>

Step 11 – Funcionalidad del Navigation Menu

Aquí simplemente tenemos que llamar a la función setupNavigationMenu(navController) que definimos a continuación, corresponde con el Step 10 del tutorial de Android Navigation – Java

    private void setupNavigationMenu(NavController navController) {
        //TODO STEP 10 - Use NavigationUI to set up a Navigation View
        // In split screen mode, you can drag this view out from the left
        // This does NOT modify the actionbar
        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        if (navigationView != null){
            NavigationUI.setupWithNavController(navigationView,navController);
        }
        //END STEP 10
    }

Y por último tenemos que capturar le callback del click en las opciones del Menú, Step 8 del tutorial de Android Navigation – Java

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //return super.onOptionsItemSelected(item);
        //TODO STEP 8 - Have Navigation UI Handle the item selection -
        // make sure to comment or delete the old return statement above
        // Have the NavigationUI look for an action or destination matching the menu
        // item id and navigate there if found.
        // Otherwise, bubble up to the parent.
        if (NavigationUI.onNavDestinationSelected(item, Navigation.findNavController(this, R.id.nav_host_fragment)))
            return true;
        else {
            return super.onOptionsItemSelected(item);
        }
        //END STEP 8
    }

Conclusiones

Bien, lo dejamos aquí. Este ejemplo se puede continuar dando funcionalidad a las otras opciones, Preferencia e E-mail, y haciendo que los fragments hagan algo util, comunicando entre sí a través del MainActivity como vimos en QuoteViewerActivity, pero el objetivo era ver cómo crear una app usando el NavigationDrawer.

A continuación tenéis el código completo del ejemplo que incluye el directorio con los recursos.