Vous êtes sur la page 1sur 16

Tutorial Para Crear Un Navigation Drawer

En Android
noviembre 23, 2014 James Revelo
Este artculo te explicar el uso del Navigation Drawer en Android para crear una
navegacin a travs de un Men deslizante.
Vers como implementar un Drawer Layout para el diseo. Aprenders a manejar los
eventos relacionados. Y tambin a complementar su funcionamiento con la action bar
mediante un Action Bar Drawer Toggle.
Antes de iniciar quiero que veas la aplicacin que podrs construir, una vez hayas
aprendido todas las lecciones de este tutorial:

Genial cierto?, puedes descargar el cdigo completo desde aqu:

Descargar Cdigo

Apyanos con una seal en tu red social favorita y consigue el cdigo completo.

Me gusta

Tweet

+1 Google

Cmo crear un men deslizante con un Navigation


Drawer?
El Navigation Drawer es un panel deslizante cuyo objetivo es dotar al usuario con una
navegacin mas cmoda entre las opciones populares de tu aplicacin.
Existen dos formas para visualizar su contenido: La primera es deslizando desde el borde
izquierdo de la pantalla hacia la derecha. Y la segunda al presionar el cono de la Action
Bar si es que se us un elemento especial llamado ActionBarDrawerToggle.
A continuacin se muestran algunos ejemplos de un Navigation Drawer:

Como ves, este componente es una de las tantas formas de navegacin en una aplicacin
Android. La gran ventaja de utilizarlo es la expansin de funcionalidades que brinda sin
tener que cambiar entre actividades.
Ejemplo de Navigation Drawer en Android
La aplicacin que construiremos le llamaremos GeekyWeb. Esta es un excelente ejemplo
para implementar un Navigation Drawer que brinde al usuario accesibilidad hacia las
categoras principales de los artculos en un blog sobre Desarrollo Web.
Categoras como: HTML, CSS, Javascript, Angular JS, Python y Ruby on Rails.
Cada vez que el usuario seleccione una categora desde el Navigation Drawer, el layout
principal se actualizar para proyectar su respectivo contenido.

Estructuralmente este proyecto se compone de un DrawerLayout que contiene un


RelativeLayout para la proyeccin de contenido y un ListView (con su respectivo
adaptador personalizado) para las opciones al desplegarse.

La idea es ir reemplazando el contenido del RelativeLayout con fragmentos personalizados


cada vez que se presione una opcin.
Crear un Proyecto en Android Studio
Abre Android Studio y crea un nuevo proyecto (GeekyWeb) con una actividad en blanco.
Llmala Main y prosigue. En este punto cabe destacar que para crear un Navigation Drawer
necesitamos usar la librera de compatibilidad v4 de Android.
As que tenemos que importarla a nuestro proyecto. Para ello sigue estos pasos:

1. Asegrate de haberla descargado la seccin Support en el SDK Manager.


2. Abre tu archivo de construccin build.gradle.
3. Ubcate en dependencies y escribe la siguiente lnea:

dependencies {
compile 'com.android.support:support-v4:19.1.0'
}

Esta instruccin le indica a gradle que necesitas incluir como dependencia externa la
librera de soporte v4, con una compatibilidad objetivo del SDK 19. Segn la versin que
vayas a compilar pues as mismo puedes especificar el nmero y cambiarla.
Crear un DrawerLayout
Un DrawerLayout es un contenedor especial de la librera de soporte, que alberga dos tipos
de contenido, el contenido principal y el contenido para el Navigation Drawer.

El contenido principal es el contenedor que veremos en la actividad normalmente. El


contenido del drawer ser aquel View que veremos cuando se despliegue el Navigation
Drawer, donde frecuentemente se usa un ListView con varias opciones de seleccin.

Para implementarlo se debe definir un nodo raz


<android.support.v4.widget.DrawerLayout> en el archivo de diseo de la actividad. Luego
aade dos hijos. El primero debe ser el layout que representar el contenido principal y el
segundo el componente que representar el Drawer.

Fjate en el archivo de diseo activity_main.xml de la aplicacin GeekyWeb:

<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">

<RelativeLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<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>

El contenido principal es representado por un RelativeLayout y el Navigation Drawer es un


ListView.

Crear Adaptador Personalizado para el ListView


El Navigation Drawer de GeekyWeb tiene una lista cuyos items poseen un icono por cada
elemento y el texto que representa la opcin. Si has visto el Tutorial de Listas y
Adaptadores en Android ya sabrs como abordar este diseo.
Se implementa una clase que represente el item de la lista para relacionar un recurso
drawable y un string.
Luego diseamos un nuevo layout con la imagen y el nombre. Y finalmente extendemos la
clase ArrayAdapter para relacionar los datos.

El archivo de diseo para los items de la lista quedara as:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:padding="10dp">

<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#fff"
android:text="Item"
android:layout_toRightOf="@+id/icon"
android:layout_centerVertical="true" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/icon"
android:layout_alignParentLeft="true"
android:layout_marginRight="16dp"
android:layout_centerVertical="true" />
</RelativeLayout>

La clase representativa de cada elemento se denomin DrawerItem y esta es su definicin:

public class DrawerItem {


private String name;
private int iconId;

public DrawerItem(String name, int iconId) {


this.name = name;
this.iconId = iconId;
}
public String getName() {
return name;
}

public void setName(String name) {


this.name = name;
}

public int getIconId() {


return iconId;
}

public void setIconId(int iconId) {


this.iconId = iconId;
}
}

Ahora solo queda implementar el adaptador usando como tipo de entrada los elementos de
la clase DrawerItem:

public class DrawerListAdapter extends ArrayAdapter {

public DrawerListAdapter(Context context, List objects) {


super(context, 0, objects);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

if(convertView == null){
LayoutInflater inflater = (LayoutInflater)parent.getContext().
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.drawer_list_item, null);
}
ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
TextView name = (TextView) convertView.findViewById(R.id.name);

DrawerItem item = getItem(position);


icon.setImageResource(item.getIconId());
name.setText(item.getName());

return convertView;
}
}

Poblar el ListView del Navigation Drawer


Una vez definido nuestro adaptador, obtendremos una instancia del DrawerLayout en el
mtodo onCreate() de Main. Luego de ello obtendremos el ListView. Y despus crearemos
una instancia del adaptador para aadirle una lista predeterminada de items. Veamos:

//Obtener arreglo de strings desde los recursos


tagTitles = getResources().getStringArray(R.array.Tags);
//Obtener drawer
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//Obtener listview
drawerList = (ListView) findViewById(R.id.left_drawer);

//Nueva lista de drawer items


ArrayList<DrawerItem> items = new ArrayList<DrawerItem>();
items.add(new DrawerItem(tagTitles[0],R.drawable.ic_html));
items.add(new DrawerItem(tagTitles[1],R.drawable.ic_css));
items.add(new DrawerItem(tagTitles[2],R.drawable.ic_javascript));
items.add(new DrawerItem(tagTitles[3],R.drawable.ic_angular));
items.add(new DrawerItem(tagTitles[4],R.drawable.ic_python));
items.add(new DrawerItem(tagTitles[5],R.drawable.ic_ruby));

// Relacionar el adaptador y la escucha de la lista del drawer


drawerList.setAdapter(new DrawerListAdapter(this, items));

Como ves, el texto de cada item de la lista fue obtenido desde un array de strings llamado
Tags, el cual est definido de la siguiente forma en strings.xml:

<string-array name="Tags">
<item>HTML</item>
<item>CSS</item>
<item>JavaScript</item>
<item>Angular JS</item>
<item>Python</item>
<item>Ruby</item>
</string-array>

Personalizar el Layout de los Fragmentos


Habamos dicho que el contenido principal de la actividad iba a variar con respecto a la
opcin elegida en la lista. Para hacer efectivo este comportamiento, primero debemos crear
el diseo de cada fragmento y extender una nueva clase de Fragment (Lee
tambin Fragmentos en una Aplicacin Android).
El fragmento simplemente mostrar un ImageView esttico ms un texto que indica el item
seleccionado en el Navigation Drawer. Veamos:

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:padding="10dp">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:text="@string/headlines"
android:id="@+id/headline"
android:layout_centerHorizontal="true" />

<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:layout_centerHorizontal="true"
android:layout_below="@+id/headline"
android:src="@drawable/article" />
</RelativeLayout>

Ahora implementaremos la clase ArticleFragment:

public class ArticleFragment extends Fragment {


public static final String ARG_ARTICLES_NUMBER = "articles_number";

public ArticleFragment() {
// Constructor vaco obligatorio
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_article, container, false);
int i = getArguments().getInt(ARG_ARTICLES_NUMBER);
String article = getResources().getStringArray(R.array.Tags)[i];

getActivity().setTitle(article);
TextView headline = (TextView)rootView.findViewById(R.id.headline);
headline.append(" "+article);

return rootView;
}
}
Cuando un ArticleFragment es creado se cambiar inmediatamente el titulo de la actividad
por una cadena del array de strings. Para saber que cadena es, se obtiene el argumento
enviado desde la actividad principal (ARG_ARTICLES_NUMBER), que representa la
posicin del item en la lista.

Luego se concatena el texto por defecto que tiene el TextView del fragmento ms el
nombre de la categora.

GeekyWeb tiene una sola clase para todos los fragmentos, ya que cumplen con el mismo
patrn, pero tal vez en tu caso no sea de esta forma. Crea distintos fragmentos
personalizados si cada opcin muestra un contenido con estructura particular.

Manejar los eventos de la lista en el Navigation Drawer


Cuando un item de la lista es clickeado, inmediatamente el contenido principal debe
actualizarse para la seleccin. Dicha actualizacin se lleva a cabo a travs del mtodo
selectItem(), el cual se invoca dentro de onItemClick() (requiere el uso de la escucha
OnItemClickListener de la lista).

Este mtodo debe reemplazar el contenido que se encuentra en el RelativeLayout del


DrawerLayout por un nuevo fragmento adaptado a las condiciones de seleccin.

Veamos:

private void selectItem(int position) {


// Crear nuevo fragmento
Fragment fragment = new ArticleFragment();
//Mandar como argumento la posicin del item
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_ARTICLES_NUMBER, position);
fragment.setArguments(args);

//Reemplazar contenido
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// Se actualiza el item seleccionado y el ttulo, despus de cerrar el drawer
drawerList.setItemChecked(position, true);
setTitle(tagTitles[position]);
drawerLayout.closeDrawer(drawerList);
}

El mtodo selectItem() recibe como parmetro la posicin del item seleccionado, el cual
debes enviar como argumento con la constante definida en ArticleFragment. Luego de
reemplazar el fragmento en el contenido principal, pasamos a iluminar el item de la lista
(setItemChecked()), cambiar el ttulo de la action bar (setTitle()) y luego cerrar el
drawer(closeDrawer()).

Ahora solo declaras una clase interna extendida de OnItemClickListener y ejecutas


selectItem() al interior de onItemClick():

/* La escucha del ListView en el Drawer */


private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}

Luego setea una instancia de esta escucha en la lista del Navigation Drawer:

drawerList.setOnItemClickListener(new DrawerItemClickListener());

Manejar los eventos de apertura y cierre del Navigation


Drawer
Usa la interfaz DrawerListener para manejar los eventos de apertura, cierre y sliding del
Navigation Drawer. En primera instancia debes declarar una nueva escucha y setearla al
DrawerLayout con el mtodo setDrawerListener().
Luego implementa el mtodo callback onDrawerOpened() que te permite actuar cuando el
drawer se expande y onDrawerClosed() cuando se cierra.

Veamos un breve ejemplo:

drawerToggle = new ActionBarDrawerToggle(


this,
drawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
){
public void onDrawerClosed(View view) {
//Acciones que se ejecutan cuando se cierra el drawer
}

public void onDrawerOpened(View drawerView) {


//Acciones que se ejecutan cuando se despliega el drawer
}
};
//Seteamos la escucha
drawerLayout.setDrawerListener(drawerToggle);

No te preocupes por el objeto de drawerToggle, en la siguiente seccin veremos su uso.


Quiero que te concentres en la implementacin de los mtodos de la escucha. Simplemente
se declara una clase annima con la sobrescritura de los mtodos de abrir y cerrar. Ambos
reciben como parmetro una instancia del drawer para que manipules cualquiera de sus
aspectos.

Usar un ActionBarDrawerToggle con el icono de la app


Un ActionBarDrawerToggle es un elemento que se implementa sobre la Action Bar para
abrir y cerrar un Navigation Drawer con el icono de la aplicacin. Normalmente se
representa con un drawable de tres barras horizontales, que se contrae y expande al abrir y
cerrar el drawer. La siguiente ilustracin muestra su aspecto:
Este componente puede accionar el Navigation Drawer debido a que implementa la escucha
DrawerListener en su definicin. Por esta razn podemos crear una nueva instancia del
ActionBarDrawerToggle y setearla como escucha de nuestro DrawerLayoutcomo hicimos
en la seccin anterior. Ten en cuenta su constructor:

drawerToggle = new ActionBarDrawerToggle(


this,
drawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
){
...

El primer parmetro es el contexto donde se ejecuta. Tambin necesita la instancia del


DrawerLayout con que se relacionar. El tercer parmetro es el drawable que representar
su presencia, en este caso es el recurso del sistema R.drawable.ic_drawer.

Y por ultimo dos strings de accesibilidad que contienen la informacin sobre la apertura y
cierre del Drawer.

Sabiendo esta informacin podemos implementar nuestros eventos de apertura y cierre del
Navigation Drawer. La idea es cambiar al titulo de la aplicacin cuando el drawer se abra.
Pero cuando est cerrado se cambiar por el ttulo del elemento seleccionado en la lista.

Veamos:

drawerToggle = new ActionBarDrawerToggle(


this,
drawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
){
public void onDrawerClosed(View view) {
//Cambiar ttulo por nombre del item en la lista
getActionBar().setTitle(itemTitle);
}

public void onDrawerOpened(View drawerView) {


//Cambiar ttulo por nombre de la actividad
getActionBar().setTitle(activityTitle);
}
};
//Seteamos la escucha
drawerLayout.setDrawerListener(drawerToggle);

Se usan dos variables auxiliares para guardar el ttulo de la actividad (activityTitle) y el de


la categora actual (itemTitle).

Finalmente solo queda implementar los mtodos callback onPostCreate() y


onConfigurationChanged() para que nuestro toggle se actualice con los cambios de la
aplicacin.

@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sincronizar el estado del drawer
drawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Cambiar las configuraciones del drawer si hubo modificaciones
drawerToggle.onConfigurationChanged(newConfig);
}
Dentro de onPostCreate() usaremos el mtodo syncState() para sincronizar el estado del
toggle si en algun momento la aplicacin es puesta en segundo plano. Y en
onConfigurationChanged() propagaremos los cambios del dispositivo.

Cambios como la modificacin de entradas por teclado, tamao de la pantalla o el cambio


de orientacin de pantalla.

Adicionalmente puedes tomar accin cuando el toggle sea presionado en la action bar con
el mtodo onOptionsItemSelected(), igual a como se hace con los action buttons:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

if (drawerToggle.onOptionsItemSelected(item)) {
// Toma los eventos de seleccin del toggle aqu
return true;
}

...//Manejo de los action buttons

return super.onOptionsItemSelected(item);
}
Para terminar ejecuta el proyecto y tendrs tu aplicacin GeekyWeb con el siguiente
aspecto:

Vous aimerez peut-être aussi