En la primera parte de este tutorial vimos como añadir un elemento Navigation Drawer en nuestra aplicación y listar en él una serie de elementos. En esta segunda parte vamos a ver como navegar por una aplicación usando el Navigation Drawer, implementar alguna funcionalidad cuando se está abriendo o cerrando, o utilizar el botón de la aplicación mostrado en la Action Bar para abrirlo y cerrarlo.

Añadiendo ActionBarCompat a nuestra aplicación

Vamos a empezar añadiendo un ActionBarCompat a nuestra aplicación, ya que será necesario para algunos de los puntos que vamos a tratar en este tutorial. Los pasos a seguir para añadir ActionBarCompat a nuestra aplicación son los siguientes:

  1. Añadimos a nuestro espacio de trabajo (workspace) el proyecto android-support-v7-appcompat pinchando en File → Import → Android → Existing Android Code Into Workspace.
  2. Seleccionamos dentro del directorio donde tenemos instalado el SDK de Android el directorio sdk/extras/android/support/v7/appcompat y pulsamos en Finish.
  3. Se añadirá a nuestro workspace el proyecto android-support-v7-appcompat, seleccionamos dentro de él el directorio lib y dentro de este hay dos librerías: android-support-v4.jar y android-support-v7-appcompat.jar, hacemos clic derecho sobre cada una de ellas y seleccionamos Build Path → Add to Build Path.
  4. A continuación hacemos clic derecho sobre el proyecto y seleccionamos Build Path → Configure Build Path. Ahora en la sección Java Build Path seleccionamos la pestaña Order and Export, donde seleccionamos las dos librerias que hemos añadido en el paso anterior, desmarcamos Android Dependencies y si aparece desmarcada la librería Android X.Y, la marcamos.
  5. El siguiente paso es hacer clic derecho sobre nuestra aplicación y seleccionamos Build Path → Configure Build Path. Seleccionamos la sección Android y dentro de esta nos vamos a Library donde pinchamos en el botón Add y seleccionamos android-support-v7-appcompat.jar. Pulsamos Apply y OK.
  6. Ahora, en nuestra aplicación, abrimos el fichero AndroidManifest.xml y en las actividades que queremos mostrar el action bar añadimos o modificamos el atributo android:theme dentro de la etiqueta <activity>:
<activity
    android:name=".MainActivity"
    android:label="@string/app_name"
    android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />

También podremos indicar que queremos mostrar el action bar en toda la aplicación definiendo este atributo en la etiqueta <application>:

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />

Ahora, cada actividad en la que queremos mostrar el action bar deberá heredar de la clase ActionBarActivity:

import android.support.v7.app.ActionBarActivity;
 
public class MainActivity extends ActionBarActivity {
 
}

Navegando a través del Navigation Drawer

El uso principal de un navigation drawer es el de servir como índice de las actividades o funciones que va a tener nuestra aplicación. En este ejemplo vamos a crear un fragment al que se le pasará un texto dependiendo de la opción seleccionada en nuestro drawer:

res/layout/fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >
 
    <TextView
        android:id="@+id/tv_fragment"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
 
</LinearLayout>

MyFragment.java

package com.amatellanes.android.examples;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
 
public class MyFragment extends Fragment {
 
    public final static String KEY_TEXT = "key_text";
 
    private String mText;
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
 
        mText = getArguments().getString(KEY_TEXT);
 
        View v = inflater.inflate(R.layout.fragment, container, false);
        TextView tv = (TextView) v.findViewById(R.id.tv_fragment);
        tv.setText(mText);
 
        return v;
    }
}

Cuando el usuario selecciona un elemento de la lista que se muestra en el drawer, el sistema invoca al método onItemClick() definido en el interfaz OnItemClickListener. En este ejemplo modificaremos el contenido del fragment y el título mostrado en el action bar dependiendo del elemento seleccionado en el drawer :

MainActivity.java

package com.amatellanes.android.examples;
 
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
 
public class MainActivity extends ActionBarActivity {
 
    private DrawerLayout drawerLayout;
    private ListView navList;
    private CharSequence mTitle;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        this.drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        this.navList = (ListView) findViewById(R.id.left_drawer);
 
        // Load an array of options names
        final String[] names = getResources().getStringArray(
                R.array.nav_options);
 
        // Set previous array as adapter of the list
        ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;String&gt;(this,
                android.R.layout.simple_list_item_1, names);
        navList.setAdapter(adapter);
        navList.setOnItemClickListener(new DrawerItemClickListener());
    }
 
    private class DrawerItemClickListener implements
            ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            selectItem(position);
        }
    }
 
    /** Swaps fragments in the main content view */
    private void selectItem(int position) {
        // Get text from resources
        mTitle = getResources().getStringArray(R.array.nav_options)[position];
 
        // Create a new fragment and specify the option to show based on
        // position
        Fragment fragment = new MyFragment();
        Bundle args = new Bundle();
        args.putString(MyFragment.KEY_TEXT, mTitle.toString());
        fragment.setArguments(args);
 
        // Insert the fragment by replacing any existing fragment
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
                .replace(R.id.content_frame, fragment).commit();
 
        // Highlight the selected item, update the title, and close the drawer
        navList.setItemChecked(position, true);
        getSupportActionBar().setTitle(mTitle);
        drawerLayout.closeDrawer(navList);
    }
 
}

Como vemos en la línea 36 usamos el método setOnItemClickListener() para definir el evento que se debe lanzar, al igual que hacemos en cualquier otra vista. Se invocará al método selectItem() donde se realizan 4 pasos:

  • Obtener a partir de la posición del item pulsado el string que se va a mostrar en el fragment.
  • Crear el fragment que se va a mostrar pasando como argumento el texto obtenido en el paso anterior.
  • Mostrar el fragment en pantalla reemplazando el que ya está por pantalla.
  • Marcar en el drawer el elemento que hemos seleccionado, con el método setTitle() actualizar el título en el action bar y cerrar el drawer.

Eventos al abrir y cerrar el Navigation Drawer

En algunos casos necesitaremos implementar alguna funcionalidad al abrir o cerrar el drawer, para ello debemos usar el método setDrawerListener() de nuestro DrawerLayout y pasarle una implementacion de DrawerLayout.DrawerListener, que es el interfaz que nos proporcionará los métodos onDrawerOpened() y onDrawerClosed().

Sin embargo, si en tu aplicacion has incluido un action bar (como es el caso de este tutorial) se recomienda extender la clase ActionBarDrawerToggle, ya que, además de implementar el interfaz DrawerLayout.DrawerListener, facilita la correcta interacción entre la action bar y el drawer.

Vamos a ver a continuación como modificar el título y la visibilidad de los elementos del action bar dependiendo del estado del drawer (abierto o cerrado). Para ello vamos a comenzar insertando un menú de elementos en el action bar.

A continuación, definimos dos strings necesarios para crear un objeto ActionBarDrawerToggle, los cuales son necesario por temas de accesibilidad de la aplicación:

res/values/strings.xml

<string name="open_drawer">Drawer abierto</string>
<string name="close_drawer">Drawer cerrado</string>