En este post vamos a ver como se puede crear una barra lateral, o Navigation Drawer como la de la imagen para una aplicacion Android usando el widget DrawerLayout de la libreria support-v4
Instalando el soporte para DrawerLayout
Si queremos usar este widget lo primero que debemos hacer es instalar la liberia support-v4 siguiendo estos pasos:
- Instalar la libreria desde el Android SDK Manager: Debemos tener instalada la opcion que pone Android Support Library
- Hacer referencia a ella en nuestro proyecto: Si usamos Eclipse deberemos copiar la libreria que esta en $ANDROID_SDK_HOME//extras/android/support/v4 que se llama android-support-v4.jar a nuestro directorio libs del proyecto
Si usamos Android Studio y usamos Gradle sera suficiente con poner una dependencia en nuestro archivo build.gradlecompile 'com.android.support:support-v4:19.0.+'
Modificando el layout y la Activity del proyecto
Lo primero que tenemos que hacer es modificar el layout que vamos a usar en nuestra Activity de la siguiente manera
<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:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/main_layout"> <TextView android:id="@+id/message" android:layout_width="fill_parent" android:layout_height="fill_parent" android:choiceMode="singleChoice" android:text="@string/hello_world"> </TextView> </RelativeLayout> <ListView android:id="@+id/navigation" android:layout_width="280dp" 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" > </ListView> </android.support.v4.widget.DrawerLayout>
Lo siguiente es crear nuestra Activity
package es.rubenjgarcia.emptydrawerlayout.app; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } }
Una vez hecho esto tendremos lo siguiente en nuestro movil
Si deslizamos el dedo desde la parte izquierda de nuestra pantalla hacia la derecha veremos como sale el menu quedando nuestra pantalla de la siguiente manera
Añadiendo el icono del navegador
Lo siguiente que vamos a hacer es añadir un icono en la parte superior del menu a la izquierda de nuestro icono para advertir al usuario que tenemos un menu lateral. El icono que vamos a usar lo podemos encontrar en el Action Bar Icon Pack de Android. Usaremos el icono de las tres barras con la sombra. Lo podemos encontrar en la carpeta Navigation_Drawer_Indicator del pack que nos hemos bajado
Configuramos nuestro estilo de la aplicacion en el archivo AndroidManifest.xml para que sea Theme.Holo.Light.DarkActionBar
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="es.rubenjgarcia.emptydrawerlayout.app" > <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.Holo.Light.DarkActionBar" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Una vez copiamos las carpetas que hay dentro del directorio Navigation_Drawer_Indicator/holo_light en nuestro proyecto mezclandolas con las que ya tenemos solo tenemos que añadir unas lineas a nuestra clase MainActivity para que salga el icono
package es.rubenjgarcia.emptydrawerlayout.app; import android.app.Activity; import android.app.Fragment; import android.app.FragmentTransaction; import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.view.GravityCompat; import android.support.v4.widget.DrawerLayout; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MainActivity extends Activity { private DrawerLayout mDrawerLayout; private ActionBarDrawerToggle mDrawerToggle; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true); final CharSequence mTitle = getTitle(); mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) { @Override public void onDrawerClosed(View view) { super.onDrawerClosed(view); getActionBar().setTitle(mTitle); invalidateOptionsMenu(); } @Override public void onDrawerOpened(View drawerView) { super.onDrawerOpened(drawerView); getActionBar().setTitle(mTitle); invalidateOptionsMenu(); } }; mDrawerLayout.setDrawerListener(mDrawerToggle); } @Override public boolean onOptionsItemSelected(MenuItem item) { return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); mDrawerToggle.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mDrawerToggle.onConfigurationChanged(newConfig); } }
Las lineas importantes de este codigo son por un lado
getActionBar().setDisplayHomeAsUpEnabled(true); getActionBar().setHomeButtonEnabled(true);
Estas 2 lineas hacen que el icono muestre una imagen y que responda a los clicks
Por otro lado esta el metodo onOptionsItemSelected donde indicamos que si se ha hecho click en el icono del drawer queremos que sea nuestro objeto mDrawerToggle el que procese ese evento. Este objeto es el que define el icono que tiene y el comportamiento al abrir y cerrar la barra lateral
Con este codigo tendriamos las siguientes pantallas en nuestro telefono
Añadiendo opciones a la barra de navegacion
Lo unico que nos falta es añadir opciones a nuestra barra de navegacion. Vamos a crear un layout para cada uno de los elementos que apareceran en la barra
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <ImageView android:id="@+id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@android:string/untitled" android:padding="10dp" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icon" android:layout_centerVertical="true" android:paddingLeft="10dp" android:textColor="@android:color/black" android:textSize="18dp" /> </RelativeLayout>
Este layout contiene una imagen y un texto que es lo que vamos a renderizar en la lista. Lo siguiente es crear las clases de apoyo. La primera es un bean donde definiremos el texto de la opcion y la imagen que vamos a mostrar
package es.rubenjgarcia.emptydrawerlayout.app.navigation; public class NavigationItem { private int imageId; private String title; public NavigationItem(int imageId, String title) { this.imageId = imageId; this.title = title; } public int getImageId() { return imageId; } public void setImageId(int imageId) { this.imageId = imageId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } @Override public String toString() { return title; } }
Y la siguiente es nuestra implementacion de la clase ArrayAdapter donde compondremos la lista
package es.rubenjgarcia.emptydrawerlayout.app.navigation; import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; import java.util.List; import es.rubenjgarcia.emptydrawerlayout.app.R; public class NavigationListAdapter extends ArrayAdapter<NavigationItem> { private Context context; public NavigationListAdapter(Context context, int resourceId, List<NavigationItem> items) { super(context, resourceId, items); this.context = context; } private class ViewHolder { ImageView imageView; TextView txtTitle; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; NavigationItem navigationItem = getItem(position); LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); if (convertView == null) { convertView = mInflater.inflate(R.layout.navigation_item, null); holder = new ViewHolder(); holder.txtTitle = (TextView) convertView.findViewById(R.id.title); holder.imageView = (ImageView) convertView.findViewById(R.id.icon); convertView.setTag(holder); } else holder = (ViewHolder) convertView.getTag(); holder.txtTitle.setText(navigationItem.getTitle()); holder.imageView.setImageResource(navigationItem.getImageId()); return convertView; } }
Vamos a añadir 3 opciones y los iconos los vamos a coger del pack de iconos que hemos descargado. En la carpeta Action_Bar_Icons/holo_light copiaremos los iconos de las carpetas 13_extra_actions_about, 13_extra_actions_help y 13_extra_actions_settings. Solo falta añadir el siguiente codigo a la clase MainActivity
List<NavigationItem> navigationItems = new ArrayList<NavigationItem>(); navigationItems.add(new NavigationItem(R.drawable.ic_action_settings, "Settings")); navigationItems.add(new NavigationItem(R.drawable.ic_action_help, "Help")); navigationItems.add(new NavigationItem(R.drawable.ic_action_about, "About")); final ListView navigation = (ListView) findViewById(R.id.navigation); NavigationListAdapter adapter = new NavigationListAdapter(this, R.layout.navigation_item, navigationItems); navigation.setAdapter(adapter);
Deberiamos ver una pantalla similar a esta en nuestro telefono
Podeis descargar el codigo de este proyecto para Android Studio en el siguiente repositorio de Github