BasicNavigationDrawer

En esta entrada vamos a construir una aplicación basada en el Navigation Drawer, pero lo vamoa a hacer desde cero, es decir, desde una aplicación en blanco. En otra entrada veremos cómo utilizar una aplicación basada en el proyecto ya definido en Android Studio como Navavigation Drawer.

Esta entrada tiene errores para las nuevas versiones, si usas las nuevas librerías AndroidX deberías leer la versión actualizada BasicNavigationDrawer – AndroidX

Creació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. Son la libresía Design y la liberría Support-v4, que en función de la versión de compilación del Sdk que usemos tendrá un número u otro. En mi caso estas son:

  • com.android.support:design:27.1.1
  • com.andorid.support:support-v4:27.1.1
Ejemplo de cómo añadir la dependencia desgin al pryoecto.

Pero para añadirlas no tenemos que sabernos los números de versión, utilizaremos el gestor de dependencias de nuestro proyecto. Para abrirlo iremos al menú Build -> Edit Libraries and Dependencies… Una vez abierto, seleccionamos la pestaña Dependencies y a la derecha vemos un menu vertical, donde pulsaremos + para añadir una librería (Library dependency), aperecerá una lista con las librerías que están disponibles para la versión de compilación del Sdk que estemos usando, podemos usar el campo de búsqueda, como se muestra en la animación anterior. Seleccionamos las dos librerías mencionadas.

Para añadir Design, buscar por : com.android.support

Para añadir support-v4, buscar por support-v4

Creando el Layout para el Navigation Drawer

Ahora vamos a crear el main-layout.xml para nuestro proyecto. Lo que haremos será ir a la documentación oficial para capturar el siguiente código que se propone, donde nos dan un layout tipo para este tipo de aplicaciones. El código que sustituye al que tiene por defecto nuestro main-layout.xml es el siguiente:

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

Como vemos el layout tiene un FrameLayout donde irá en tiempo de ejecución un fragment. Este FrameLayout será nuestra vista por defecto cuando el menú esté oculto. También vemos que tiene un ListView que actuará como menú en nuestro caso.

Vamos a crear un Toolbar para nuestra aplicación, donde pondremos algunos iconos y herramientas. Añadimos por tanto un nuevo layout, utilizando New->Layout resource file que llamaremos toolbar, (toolbar.xml) El código del ConstraintLayout que genera por defecto para ese layout lo sustituimos por este:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="?attr/actionBarTheme" />
</android.support.constraint.ConstraintLayout>

Fijaros que el ConstraintLayout que actua como root element, lo dejamos con …width=match_parent para que coja el ancho de la pantalla, pero el hight lo colocamos a wrap_content para que tome el tamaño del toolbar. El widget.Toolbar lo hemos añadido desde la paleta de Containers en el editor visual de layouts. Su propiedad height la hemos seleccionado, para ello hemos pulsado en los que salen a continuación del nombre de la propiedad en la lista de Attributes. Al pulsar en los sale un selector de recursos y buscamos en la lista actionBarSize que tiene el tamaño apropiado que da Android a la ActionBar.

Ahora vamos a cambiar el layout activity_main.xml.

  1. Por un lado vamos a incluir nuestro Toolbar recien creado
  2. Por otro vamos a cambiar el ListView que nos han puesto como ejemplo en Android Developers por un widget.NavigationView accesible desde la Pallete de Containers en el editor visual de layouts.

1- Incluir el Toolbar

Para cambiar incluir el Toolbar abrimos nuestro activity_main.xml e incluimos el toolbar como primer elemento de nuestro Layout. Para ello en la paleta Containers podemos usar <include> que nos abrirá un selector del que elegiremos nuestro toolbar.xml (toolbar).

Pero esto haría que la primera View en la jerarquía de nuestro drawer_layout sea el toolbar y según la documentación:

La vista de contenido principal (el FrameLayout anterior) tiene que ser el primer campo secundario del DrawerLayout porque la disposición XML implica un ordenamiento z y el panel lateral tiene que estar sobre el contenido.


Android Developers

Por tanto, para que la ordenación z funcione, es decir, para que el panel lateral también esté por encima de nuestro contenido principal, incluimos un constraint layout como primer elemento y dentro metemos el toolbar seguido del FrameLayout. Esto lo hacemos con el editor visual, aquí queda el código del mail_layout.xml hasta ahora:

?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
    <!-- The main content view -->
    <android.support.constraint.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <include
            layout="@layout/toolbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <FrameLayout
            android:id="@+id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </android.support.constraint.ConstraintLayout>

    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>

Como vemos el tag <include> tiene el width y el height a wrap_content. El height está bien, puesto que cogerá el alto de nuestro toolbar que pusimos que era el que android tuviera por defecto. Pero el width deberíamos ponerlo a match_parent, sin embargo en el desplegable de la propiedad layout_width no aparece, tendremos que ponerlo en el texto del xml o en la misma propiedad o bien ponerle constraints a derecha e izquierda con un padding de cero.

El código correcto para el tag <include> sería el siguiente:

<include
            layout="@layout/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

2- Cambiar el ListView por un NavigationView

Utilizando el editor de layouts eliminamos el ListView (left_drawer) y lo sustituimos por un NavigationView que encontramos en la paleta de Containers. Fijamos algunas propiedades:

  • width=wrap_content para que se ajuste al contenido y no solape completamente nuestro contenido principal cuando se desplace por encima de este.
  • fijamos el id a nvNavView.

Hasta ahora tenemos una aplicación con la apariencia de la imagen. Al desplazar el dedo de izquierda a derecha aparecerá el NavigationView, nuestro nvNavView que no tiene nada todavía, ni tiene cabecera, ni el toolbar tiene texto y ademas aprece arriba de todo el ActionBar con el nombre de la aplicación.

Si queremos quitar el ActionBar y que no aparezca el nombre de la aplicación debemos modificar el recurso del tema y cambiarlo por NoActionBar. Esto está en los recursos styles.xml, y el <style name=”AppTheme” cambiarlo para que su parent sea NoActionBar. El código correcto sería:

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

Ahora tenemos nuestra aplicación sin ActionBar (sin titulo encima).

Añadir soporte para el ToolBar

Añadimos el soporte para nuestra toolbar en el onCreate de la MainActivity. Pero lo haremos apoyándonos en una función, para poder mejorarla luego independientemente. El código sería:

Para que en nuestra toolbar aparezca el título de la aplicación, deberemos llamar a la función setSupportActionBar() y pasarle un objeto java instanciado desde el recurso. Pero para ello debemos asegurarnos que el ActionBar lo hemos eliminado, usando NoActionBar como AppTheme, puesto que no son compatibles ambas ToolBars activas simultáneamente (da error al arrancar la App).

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setToolbar();
    }
    
    private void setToolbar(){
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }

Implementando el Burguer Menú

Primero creamos un nuevo recurso Image Asset como vemos en la imagen, donde hemos elegido en el primer desplegable Icon Type la opción Action Bar and Tab Icons, le hemos puesto el nombre ic_home y pulsando en la imagen de Clip Art aparece el selector de iconos, donde seleccionamos Navigation y por fin el icono Menu que vamos a utilizar.

Lo siguiente que tenemos que hacer es añadir este icono en el Toolbar que hemos instalado, para que al pulsar en el se abra el Navigation Drawer. Esto lo haremos en dos pasos.

  1. Instalar el icono en el Toolbar
  2. Configurarlo para que al pulsarlo se abra el navigation drawer.

1- Instalar el icono en el Toolbar

En el primer paso el código que tenemos que añadir en el método que hemos creado para instalar el toolbar (SetToolbar()) es el siguiente:

getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_home);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

La primera línea establece cual es el icono que se va a utilizar para ir a home. En realidad, lo que estamos haciendo es preparar el toolbar para que vaya a una activity padre de la actual, pero en vez de dejar la flecha atras que sale por defecto, utilizamos el icono ic_menú que hemos creado. La segunda línea habilita su utilización.

2- Responder al click en el menú

En segundo lugar, una vez colocado el icono, debemos hacer que el drawer se despliegue. Para ello utilizamos el mismo método que se utiliza para tratar los eventos onClick en el menú de nuestra aplicación. Usamos el callback onOptionsItemSelected(MenuItem item)

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                // Código necesario para desplegar el Navigation Drawer.
                // ...
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

Vemos cómo usamos el switch con el Id del item recibido. El Toolbar tiene por defecto implementado ya el botón Home, pero lo hemos cambiado y habilitado en el paso anterior, pero existe y su id es el android.R.id.home.

Para abrir el navigation drawer tenemos que instanciarlo en un objeto java como miembro de la clase activity utilizando para ello el findViewById de siempre ya que lo tenemos definido como un layout, en concreto es nuestro main_layout.xml donde como vemos tenemos en la raiz del layout un DrawerLaout.

Una vez instanciado llamaremos a su método openDrawer pasándole como gravity START, puesto que es lo que hemos colocado en el layout. Como hemos dicho antes, START indica que va de izquierda a derecha si está configurado el sistema de esa forma (que es la por defecto) si estuviera para operar de derecha a izquierda, START tomaría entonces la acción de derecha a izquierda. El código completo que tenemos entonces de momento en nuestra MainActivity es:

public class MainActivity extends AppCompatActivity {

    private DrawerLayout drawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setToolbar();
        drawerLayout=(DrawerLayout) findViewById(R.id.drawer_layout);
    }

    private void setToolbar(){
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_home);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                // Código necesario para desplegar el Navigation Drawer.
                drawerLayout.openDrawer(Gravity.START);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Personalizando el Drawer

Añadiendo un Header

Queremos añadir una cabecera en el drawer, tal como aparece en la imagen adjunta.

Como vemos tenemos una imagen (fondo oscuro y en la parte inferior unos platos) a al que hemos superpuesto en la parte superior yn texto que pone “Recetas Caseras” en color blanco. Tenemos pues que conseguir varias cosas:

  • Añadir la imagen al proyecto
  • Crear el color blanco en el proyecto o usar uno predefinido
  • Crear un layout para el header que contendrá la imagen y el texto.

Añadir la imagen al proyecto.

En los descargables asociados a este artículo (ver botón más abajo) tenemos uno con los recursos utilizados, en concreto la imagen, pero podéis usar otra cualquiera.

Para añadir la imagen al proyecto hay que copiarla en la carpeta drawables del proyecto. Para ello podemos localizar dicha carpeta en el explorador de archivos del sistema operativo y copiarla allí. Para saber donde está rápidamente, podemos pulsar botón derecho encima de Drawable y seleccionar “Show in File Manager” lo que nos abre el explorador de archivos con la ubicación de dicha carpeta en nuestro sistema. Copiamos dentro de Drawable el .jpg y aparecerá en su sitio en la vista Android.

También podemos usar el Resource Manager, para gestionar todos los recursos de la App. Al abrir el Resource Manager seleccionamos el tipo de recurso y pulsamos en + , se abrirá un selector para seleccionar los ficheros de imagen de nuestro disco duro. En el botón de recursos de la App al final de este artículo podéis descargar los recursos utilizados en esta aplicación. Los colocáis en una carpeta de vuestro disco duro y los importáis con el Resource mánager. Ver imagen.

Crear el color blanco

Para crear el color blanco nos situamos en la vista Android en la carpeta values, vemos el archivo colors.xml, lo editamos y creamos un nuevo color blanco, como se ve a continuación:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
    <color name="Blanco">#FFFFFF</color>
</resources>

Crear el Layout e integrar imagen y texto

Creamos un nuevo layout con New->Resource File, seleccionando tipo Layout y como root del layout un FrameLayout. Al layout le llamaremos header, con lo que tendremos en la carpeta de layouts un nuevo fichero header.xml

Añadimos un ImageView y un TextView. En el ImageView colocaremos la imagen que hemos añadido. Para ello seleccionamos la propiedad srcCompat y elegimos el drawable header.png que hemos colocado ahí. Ajustamos el ImageView a wrap_content tanto en alto como en ancho, pero la imagen no queda ajustada. Para ello seleccionamos la propiedad adjustViewBounds y la colocamos a true, esto hace que la imagen y el ImageView tomen el mismo tamaño.

En el textView colocamos el texto que queramos, en nuestro ejemplo “Recetas Caseras” al que le ponemos el color blanco textColor=@Color/Blanco que hemos creado previamente y le aumentamos el tamaño con la propiedad textAppearance asignamos el valor AppCompat.Large. Además colocamos un margen a la izquierad y arriba de 50dp para que aparezca desplazado como en la imagen.

Ahora tenemos que asignar el nuevo layout con el header al Drawer para que se asigne como cabecera de este. Para ello, en el XML que define el drawer, el activity_main.xml en su NavigationView asignamos a la propiedad headerLayout el valor @layout/header, de forma que el código XML del Navigation View queda como a continuación. En la imagen vemos la propiedad en el panel de propiedades.

    <android.support.design.widget.NavigationView
        android:id="@+id/nvNavView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/header"/>

Creando el Menú

El menú irá dentro del Navigagion Drawer, en la parte de abajo, es decir debajo del header. Para ello vamos a crear un menú como hemos hecho en otros ejercicios. Creamos un nuevo recurso menú con New->Resource File de tipo Menu. Le vamos a llamar nav_options. Añadimos un grupo en el que irán cada uno de los items del menú y luego un item con un submenú para preferencias y e-mail.

El Component Tree del menú quedaría como en la imagen y el xml completo del menú, tras asignar los iconos apropiadamente sería el siguiente.

Para añadir los iconos procederemos de la misma manera que hemos hecho para crear el menú de hamburguesa. En los recursos que acompañan a esta entrada, al final de la misma, se pueden obtener los iconos que se han utilizado para este ejemplo.

El menú deberá instalarse, asociarse, a nuestro NavigationView, esto lo hacemos en la propiedad menú de nuestro nvNavView en el activity_main.xml, seleccionando el menú que acabamos de crear.

Recordar igualmente que en vez de poner los textos directamente en el titulo de cada item, deberíamos crear recursos String y ser estos los que se asignen a los títulos, esto nos dará la posibilidad de traducir la app.

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

    <group >
        <item
            android:id="@+id/itGuisos"
            android:icon="@drawable/ic_guisos"
            android:title="Guisos y Horno" />
        <item
            android:id="@+id/itPastas"
            android:icon="@drawable/ic_pasta"
            android:title="Pastas y Ensaladas" />
        <item
            android:id="@+id/itFritos"
            android:icon="@drawable/ic_fritos"
            android:title="Fritos y Plancha" />
        <item
            android:id="@+id/itSopas"
            android:icon="@drawable/ic_sopas"
            android:title="Sopas y Cremas" />
        <item
            android:id="@+id/itPostres"
            android:icon="@drawable/ic_postres"
            android:title="Postres" />
    </group>
    <item android:title="Opciones">
        <menu>
            <item
                android:id="@+id/itPreferencias"
                android:icon="@android:drawable/ic_menu_preferences"
                android:title="Preferencias" />
            <item
                android:id="@+id/itEmail"
                android:icon="@android:drawable/sym_action_email"
                android:title="E-Mail" />
        </menu>
    </item>
</menu>

Ahora tenemos que asociar a cada uno de los elementos del menú un Fragment que será mostrado, cuando se pulse, en el Frame Layout que hemos colocado en el main_activit.xml .

Creando los Fragments

Ahora vamos a crear unos fragments muy sencillos que nos servirán simplemente para crear esta demo de forma sencilla. Cada uno ya posteriormente realizará en los fragments lo que necesite.

Lo primero que vamos a hacer (no es necesario, sólo por tener todo más organizado) es clasificar en Packages las activities y los fragments. Para ello creamos dos Packages, Activities y Fragments con New->Package tal como se muestra en la imagen

Una vez creados ambos Packages arrastramos el código Java de nuestro MainActivity al Package Activities.

Ahora con el menú contextual (botón derecho) desde Fragments añadimos 5 Blank Fragments con la opción New->Fragment y con las opciones como se muestra en la imagen:

El textView por defecto que aparece en cada uno de los fragments lo cambiamos por el que se muestra en el siguiente código (del fragment_fritos.xml) que servirá de ejemplo, cambiando apropiadamente el texto a mostrar:

En la imagen se ve el preview del fragment en el editor:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Fragments.FritosFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:text="Fritos y Plancha"
        android:textAlignment="center"
        android:textSize="52dp" />

</FrameLayout>

Añadiendo funcionalidad al Navigation Drawer

Respondiendo a los clicks en el Navigation Menu

Para capturar la funcionalidad necesitamos un listener como es habitual. En este caso es el NavigationView (el desplegable) donde los usuario hacen click. El evento por tanto habrá que capturarlo en el onclick correspondiente de un listener que escuche eventos producidos en el NavigationView.

Este es el esqueleto de código necesario para capturar la funcionalidad deseada, lo vamos explicando y luego lo completaremos.

    NavigationView navigationView;
    ....    
        navigationView = findViewById(R.id.nvNavigationView);

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                switch (menuItem.getItemId()){
                    case R.id.itFritos:
                        break;
                    case R.id.itGuisos:
                        break;
                    case R.id.itPastas:
                        break;
                    case R.id.itPostres:
                        break;
                    case R.id.itSopas:
                        break;
                }
                return true;
            }
        });

    }

El listener es el OnNavigationItemSelectedListener() que tiene que establecerse (set) en el objeto NavigationView con un setNavigationItemSelectedListener() al que le pasamos un new del OnNavigationItemSelectedListener(). Por tanto tenemos que instanciar el NavigationView a nivel de clase por ejemplo, y lo capturamos del layout al comienzo del onCreate de la actividad principal con el ya conocido findViewById().

En el listener vemos que nos aparece un onNavigationItemSelected() que recibe un MenuItem. Capturamos el id del item con getItemId() y con el hacemos un switch con los ids de todos los menu items que hemos colocado en nuestro menú.

Lo que tenemos que hacer ahora en cada una de las opciones es abrir una Fragment Transaction para reemplazar el fragment que está en nuestro content_frame (un FrameLayout que tenemos definido en el activity_main.xml) que es donde se van a ir mostrando los fragments que vamos seleccionando. Pero estamos hablando de reemplazar un fragment que hay ahí, pero no tenemos ninguno. Por tanto vamos a crearlo y asignarlo por defecto.

Creando un Fragment por defecto

Creamos un nuevo fragment de la misma forma que hemos realizado con los anteriores y lo llamamos DefaultFragment. Su layout lo editamos para que contenta la imagen que aparece en la cabecera centrada en la pantalla, como se muestra en la imagen. Utilizamos la propiedad layout_gravity de la ImageView, poniéndola a center vertical .

Para colocar este fragment al principio lo haremos en el onCreate de la MainActivity. Crearmos una función privada que llamamos setDefatulFragment() y en ella hacemos la Fragment Transaction.

Creando las Fragment Transactions

Como sabemos la Fragment transaction la tenemos que hacer para todos los items de nuestro menú también, por lo que sería mejor colocarla en una función privada también. Además queremos que el título que aparece en el toolbar cuando hay un fragment activo cambie en función del fragment.

Vamos a ver el código de estas dos funciones.

    private void setDefaultFragment(){
        changeFragment(new DefaultFragment(), null);
        getSupportActionBar().setTitle(R.string.nombre_app);
    }

    private void changeFragment(Fragment fragment, MenuItem item){
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.content_frame,fragment)
                .commit();
        if (item!=null){
            item.setChecked(true);
            getSupportActionBar().setTitle(item.getTitle());
        }
        drawerLayout.closeDrawers();

    }

La función que realiza la transacción finalmente es changeFragment() a la que le pasamos el fragment al que cambiar (un objeto java instanciando la clase del fragment, luego veremos donde se crea) y un item, de forma que nos sirva para coger el título del item y colocarlo en el Toolbar.

Utilizamos el SupportFragmentManager() para crear la transacción que reemplaza el fragment fragment en el content_frame (recordar el FrameLayout en el xml). La transacción la finalizamos con commit().

En la función hemos permitido que el parámetro item venga a null, puesto que también la vamos a llamar desde nuestra función setDefaultFragment() y en ella no se ha pulsado ninguna opción de menú, es llamada simplemente desde el onCreate de la activity para poner nuestro primer fragment.

Vemos que cuando viene un item, lo que hacemos es marcarlo con el setChecked(true) para que en el menú de navegación se coloree de otra forma, lo que nos indica que estamos en esa opción. Por otro lado con el SupportActionBar colocamos el título del Toolbar pasándole el getTitle() de nuestro item recibido. En la función setDefaultFragment() hemos usado un recurso String que hemos creado con el valor “Recetas Caseras”.

Creando los Fragments

Bien, ya tenemos las funciones que nos van a permitir colocar los fragments en su sitio, tanto para el DefaultFragment, como para el resto. Ya sabemos que para colocar el DefautFragment tenemos que llamar a la función en el onCreate, simplemente llamando a la función. Para colocar el resto de fragments lo tendremos que hacer en el swicth que creamos para diferenciar en que opción de menú pincho el usuario.

El código resultante podría ser algo asi: (lo comentamos luego)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setToolbar();
        drawerLayout=(DrawerLayout) findViewById(R.id.drawer_layout);
        navigationView=(NavigationView) findViewById(R.id.nvNavView);

        setDefaultFragment();

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                boolean doChange=false;
                Fragment fragment = null;

                switch (item.getItemId()){
                    case R.id.itFritos:
                        doChange=true;
                        fragment = new FritosFragment();
                        break;
                    case R.id.itGuisos:
                        doChange=true;
                        fragment = new GuisosFragment();
                        break;
                    case R.id.itPastas:
                        doChange=true;
                        fragment = new PastasFragment();
                        break;
                    case R.id.itPostres:
                        doChange=true;
                        fragment = new PostresFragment();
                        break;
                    case R.id.itSopas:
                        doChange=true;
                        fragment = new SopasFragment();
                        break;
                }

                if (doChange){
                    uncheckItems(navigationView);
                    changeFragment(fragment,item);
                }
                return true;
            }
        });
    }

    private void uncheckItems(NavigationView navigationView){
        int size = navigationView.getMenu().size();
        for (int i = 0; i < size; i++) {
            navigationView.getMenu().getItem(i).setChecked(false);
        }
    }

Hemos creado una función booleana que permite saber que opciones del menú provocan o no un cambio de fragment, (en este ejemplo todas, pero podría ser que no). Por su parte en cada uno de los case creamos un new fragment correspondiente con la opción seleccionada, que asignamos a la variable local fragment, que será la que se pase a nuestra función changeFragment.

Como vemos hemos creado también una función unckeckItems() para que desmarque todos los elementos del menú, ya que si no se irán quedando marcados conforme el usuario vaya pulsando unos y otros y al final quedarán todos marcados. De esta forma, independientemente de cuantos tenga los desmarcamos todos.

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 y un fichero de recursos.