Una de las novedades que ha traído Google IO 2013 ha sido la adopción como un estándar de la barra de navegación conocida como Navigation Drawer (en español cajón de navegación) en la versión 13 de la librería de soporte de Android. Google ha proporcionado toda las herramientas y documentación necesarias para que cualquier desarrollador pueda implementarla en sus aplicaciones. Toda la información está disponible en la guía de diseño de Android disponible aquí.

navigation_drawer_overview

La popularidad de este componente ha ido creciendo últimamente, pero cuando cualquier desarrollador quería incluir el componente Navigation Drawer en sus aplicaciones debía implementarla él mismo, por lo que podíamos encontrar una barra de navegación diferente en las aplicaciones. Gracias a que Google ha incluido este componente de manera nativa, empezaremos a ver que todas las aplicaciones empiezan a adoptarla, y de esta manera mejorar la experiencia del usuario.

A continuación vamos a desarrollar una aplicación para mostrar la implementación de un componente Navigation Drawer. Después de crear un nuevo proyecto debemos descargar la librería de soporte de Android, para ello hacemos lo siguiente:

  1. Hacemos clic derecho sobre el nombre del proyecto Android en el Explorador de Proyectos (Project Explorer) de Eclipse.
  2. Seleccionamos Android Tools y luego Add Support Library…
  3. Aceptamos la licencia y empezará la instalación.

Una vez instaladas la librería de soporte ya podemos empezar a escribir la aplicación. Lo primero es crear una vista y definir en ella un componente DrawerLayout como el objeto raíz de la vista. Dentro de ella, añadimos una lista, que contendrá el contenido principal de la vista (cuando el componente Navigation Drawer esté oculto), y otra vista que contendrá el contenido del componente Navigation Drawer. Hay que tener en cuenta varios factores:

  • La vista principal de la vista debe de ser el primer hijo del componente DrawerLayout, ya que hay mantener el orden de los componentes en el fichero XML.
  • La vista principal tiene asignado el valor «match_parent» tanto en la altura como en el ancho, ya que la vista deberá ocupar toda la pantalla cuando la barra de navegación esté oculta.
  • La vista que incluyamos en la barra de navegación debe especificar un valor para el atributo android:layout_gravity. Especificamos el valor «start» para dicho atributo.
  • Por último hay que especificar un ancho en unidades dp y en la altura especificamos el valor «match_parent». El ancho de la barra de navegación no debería ser mayor de 320dp para permitir que siempre haya una porción del contenido principal visible.
<?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 -->
 
    <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:background="@android:color/white"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
 
</android.support.v4.widget.DrawerLayout>

Una vez tenemos la vista hecha podemos pasar definir la lógica. En este primer ejemplo sobre Navigation Drawer, vamos a mostrar simplemente una lista de opciones en la barra de navegación. Definimos el fichero arrays.xml en el directorio /res/values/:

<?xml version="1.0" encoding="utf-8"?>
<resources>
 
    <string-array name="nav_options">
        <item>Option 1</item>
        <item>Option 2</item>
        <item>Option 3</item>
        <item>Option 4</item>
        <item>Option 5</item>
        <item>Option 6</item>
    </string-array>
 
</resources>

Y a continuación ya podemos crear la actividad principal en el fichero MainActivity.java:

package com.amatellanes.android.examples;
 
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
 
public class MainActivity extends FragmentActivity {
 
    private ListView navList;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        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);
    }
}

Con estos sencillos paso ya estará funcionando la barra de navegación. Aparecerá por encima de la vista principal que hemos definido ya sea deslizando nuestro dedo desde el borde izquierdo de la pantalla o tocando su icono en la barra de acciones. Puedes ocultar la barra de cuatro manera diferentes: deslizándola con el dedo hacia la izquierda, pulsando el botón de la barra de acciones, pulsando el botón Atrás de nuestro dispositivo o pulsando cualquier zona de la pantalla que esté fuera de la barra.

ejemplo-navigationdrawer-parte1

Fuente: http://amatellanes.wordpress.com/2013/05/24/ejemplo-de-navigation-drawer-en-android-parte-i/
Descargar código | Github

Ahora vamos a definir el menú que aparecerá en nuestro action bar. Creamos el fichero res/menu/main.xml y definimos el número de elementos que vamos a añadir. Para que los elementos que añadamos aparezcan directamente como un botón de acción debemos incluir en cada etiqueta <item> el atributo showAsAction="ifRoom":

res/menu/main.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:yourapp="http://schemas.android.com/apk/res-auto" >
 
    <item
        android:id="@+id/action_search"
        android:icon="@drawable/ic_action_search"
        android:title="Buscar"
        yourapp:showAsAction="ifRoom"/>
 
</menu>

Os recomiendo descargar los iconos oficiales de Android para la action bar que nos proporciona Google desde este enlace y que son los iconos que he usado en este tutorial.

Ahora en el código de nuestra actividad sobrescribimos el método onCreateOptionsMenu() e inflamos el menú que acabamos de crear para añadirlo en la action bar:

MainActivity.java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

Para definir un ActionBarDrawerToggle indicamos en el constructor de la clase el elemento DrawerLayout que contiene drawer, un icono (puedes descargar el paquete de icono oficiales en este enlace), un recurso del tipo string para describir la apertura del drawer y otra para el cierre que se definen por temas de accesibilidad de la aplicación:

MainActivity.java

import android.support.v4.app.ActionBarDrawerToggle;
...
 
public class MainActivity extends ActionBarActivity {
 
    ...
 
    private ActionBarDrawerToggle drawerToggle;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        mTitle = getTitle(); // Get current title
 
        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<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, names);
        navList.setAdapter(adapter);
        navList.setOnItemClickListener(new DrawerItemClickListener());
        drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
                R.drawable.ic_navigation_drawer, R.string.open_drawer,
                R.string.close_drawer) {
 
            /**
             * Called when a drawer has settled in a completely closed state.
             */
            public void onDrawerClosed(View view) {
                getSupportActionBar().setTitle(mTitle);
                // creates call to onPrepareOptionsMenu()
                supportInvalidateOptionsMenu();
            }
 
            /**
             * Called when a drawer has settled in a completely open state.
             */
            public void onDrawerOpened(View drawerView) {
                getSupportActionBar().setTitle("Selecciona opción");
                // creates call to onPrepareOptionsMenu()
                supportInvalidateOptionsMenu();
            }
        };
 
        // Set the drawer toggle as the DrawerListener
        drawerLayout.setDrawerListener(drawerToggle);
 
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    /*
     * Called whenever we call invalidateOptionsMenu()
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content
        // view
        boolean drawerOpen = drawerLayout.isDrawerOpen(navList);
        menu.findItem(R.id.action_search).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
}