miércoles, 27 de abril de 2016

Navigation Drawer (NavigationView)

Navigation Drawer (NavigationView)



En este nuevo artículo del curso vamos a tratar otro de los componentes relacionados con la capa de presentación de nuestras aplicaciones, el menú lateral deslizante, o Navigation Drawer. Este menú es el que aparece en muchas aplicaciones al deslizar el dedo desde el borde izquierdo de la pantalla hacia el lado opuesto (también puede aparecer en el lado derecho, pero es menos frecuente).
El navigation drawer está disponible como parte de la librería de compatibilidad android-support-v4. Si estamos trabajando con Android Studio, en la mayoría de los casos no tendremos que añadir esta librería al proyecto de forma explícita ya que muy probablemente tengamos ya añadida la librería appcompat-v7 (se incluye por defecto en los proyectos de Android Studio), que depende de la primera.
Vamos a crear un menú lateral que cumpla todo lo posible las directrices marcadas por las nuevas guías de diseño de Material Design. Dicha guía establece que el menú de navegación lateral debe pasar por encima de la action bar y por debajo de la status bar (que será translúcida en Android 5.0 y posteriores).

Veremos cómo conseguir este efecto para versiones de Android a partir de la 5.0 Lollipop (API 21), mientras que en versiones anteriores la status bar permanecerá de color negro.
El Navigation Drawer es una gran forma de organizar tu app ya que permite disponer de todo el espacio en pantalla además de ser conocido por los usuarios al utilizarse en la gran mayoría de las apps, entre ellas las de Google.

Éste último ha publicado durante la I/O 2015 una nueva librería, Android Design Support Library, que permite crear un Navigation Drawer fácilmente entre otros elementos, como pueden ser los botones de acción flotantes (floating action buttons), pestañas (tabs), etc.

Vamos a empezar a crear un proyecto con una actividad vacía, nombre del proyecto Navigation Viewer, minSdkVersion 15. Nuestro archivo app.gradle debería verse así:
Lo más seguro es que les dará error, ya que si no han instalado la version 22, les pedirá descagarla. Esto es sencillo, el mismo IDE te dice que descargar, durará dependiendo del acceso a internet que tengas.
Primero vamos a ver el archivo  MainActivity.java al completo para después ir analizándolo cada parte del mismo.
Lo primero que vemos arriba son todos los elementos que se han importado, hay que tener cuidado ya que algunas veces cuando añades una, por ejemplo,  Toolbar, en vez de importarte import android.support.v7.widget.Toolbar; te importa otro elemento diferente. Esto ocurre con varias de ellos.
Lo siguiente que hacemos es declarar los elementos necesarios dentro de nuestra case principal, pero fuera del método  onCreate:
En el método  onCreate damos soporte a la  Toolbar que más adelante añadiremos al layout  activity_main .xml, aparte de mostrar el icono característico de las tres rayas paralelas en la ActionBar o  Toolbar (como gustes llamar a la barra superior de la app).
El código restante dentro del método  onCreate son los engranajes para hacer funcionar al navigation drawer mediante el nuevo  View llamado NavigationView. Básicamente hacemos referencia al mismo, y para que quede más limpio el código, creamos un método llamado setupNavigationDrawerContent, en el cual le pasamos la instancia que hemos creado  navigationView. El método lo colocaremos fuera del método onCreate siendo el siguiente:
Cómo se puede observar en la figura anterior, básicamente estamos haciendo referencia a todos los elementos que habrá en el Nacivigation Drawer. Así, con el  switch, cuando el usuario seleccione uno de los elementos, ocurrirá lo siguiente para cada uno de ellos:
  1. Se marcará como seleccionado el ítem en cuestión gracias a  menuItem.setChecked(true).
  2. El  TextView que se encuentra en mitad de la pantalla cambiará de nombre, obteniendo el mismo del título del ítem presionado, textView.setText(menuItem.getTitle());.
  3. Se cerrará el navigation drawer mediante  drawerLayout.closeDrawer(GravityCompat.START);.
Y para finalizar, el código siguiente es para abrir el navigation drawer si se presiona sobre el botón de las tres rayas en la Toolbar, mediante el siguiente método:

Layout activity_main.xml

El contenedor principal es, evidentemente, un  DrawerLayout, con un atributo que hay que mencionar por ser muy importante, que es el android:fitsSystemWindows="true", para evitar que los elementos de la pantalla superpongan las barras del sistema. El DrawerLayout se encarga de poder tener un Navigation Drawer además de contener el resto de elementos de la actividad principal.
Dentro del  DrawerLayout se puede ver que hay un  FrameLayout que contiene una  Toolbar, un TextView, y el elemento estrella, un  NavigationView.
Vamos a ver cada uno de los nuevos atributos del NavigationView:
  1. El primer atributo que quiero destacar es el  android:fitsSystemWindows="@bool/fitsSystemWindows", ya que como ven no le estamos dando un valor  true o  false, le estamos indicando que le daremos el valor  @bool/fitsSystemWindows, este valor lo determinaremos nosotros en los archivos  attrs.xml que haremos para cada versión, ya que casi todas las versiones necesita que sea  True, excepto para KitKat es necesario que sea  False. También verás en la  Toolbar o en el  FrameLayout que también utilizamos esto, además de una altura que variará en el FrameLayout y en el margen superior de otro  FrameLayout.
  2. El atributo relevante es  app:headerLayout="@layout/navigation_drawer_header" se encarga de permitirte que puedas añadir un header (la parte superior clásica con la imagen, el avatar, etc) al navigation drawer, este header lo tienes que crear en otro  layout que verás más adelante y que se llamará  navigation_drawer_header.xml.
  3. El atributo app:menu="@menu/navigation_drawer_menu" es para indicarle los elementos que tendrá el navigation drawer. Es aquí donde se encuentra la magia ya que te evitas tener que hacer un  RecyclerView o un  ListView además de tener que personalizar cada item para que cumpla las especificaciones de material design.
  4. El último atributo  app:theme="@style/NavigationViewTheme" lo he añadido yo personalmente ya que, por ahora, los textos están utilizando por defecto la fuente Roboto Regular, y si has visitado las especificaciones de material design para el navigation drawer, verás que debería ser Roboto Medium. Con este método lo arreglamos después en nuestro archivo  styles.xml. Es probable que esto más adelante no haga falta ya que lo arregle Google por defecto.

Layout navigation_drawer_header.xml


Este  Layout no tiene nada de especial, simplemente sería la parte superior de la Figura 1. con el logo, fondo y textos que he añadido yo personalmente. Simplemente fíjate que la línea destacada es la que se encarga de que el margen del avatar sea diferente en función de en que versión de Android estamos ejecutando la app ya que si no tiene una status bar translucida el margen sería de  16dp y si la tiene translucida debería ser de 41dp para que no quede por debajo de ella viéndose francamente mal.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="192dp"
  android:gravity="bottom"
  android:theme="@style/ThemeOverlay.AppCompat.Dark">
  <ImageView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:scaleType="centerCrop"
      android:background="@drawable/header" />
  <ImageView
      android:layout_marginLeft="16dp"
      android:layout_marginTop="@dimen/navigation_drawer_header_margin"
      android:layout_width="64dp"
      android:layout_height="64dp"
      android:scaleType="centerCrop"
      android:src="@drawable/logo" />
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="52dp"
      android:layout_gravity="left|bottom"
      android:gravity="center"
      android:orientation="vertical"
      android:paddingBottom="8dp"
      android:paddingLeft="16dp"
      android:paddingRight="16dp">
      <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="center"
          android:gravity="center_vertical"
          android:text="Desarrollador Android"
          android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
      <TextView
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_gravity="center"
          android:gravity="center_vertical"
          android:text="codeFalcon@gmail.com"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
  </LinearLayout>
</FrameLayout>

Menú navigation_drawer_menu.xml

Aquí es donde se hace la magia como he mencionado anteriormente. Con la Android Design Support Library nos ahorramos tener que crear la estética de cada ítem, de añadir divisores (dividers) o los subtítulos (subheaders) ya que se hace todo automáticamente con el siguiente código, el cual desguazaremos tras verlo al completo.






Respecto al menú a utilizar, ya dijimos que se definirá utilizando la sintaxis habitual de los recursos de tipo menú. Primero crearemos el menu, damos click derecho a la carpeta RES de nuestro proyecto, New->Android Resource File
Escogemos el Resource type “menu” y de nombre drawer:
Se acaba de crear una subcarpeta llamada menu
Además tendremos otro menú llamado menu_main:
Comentemos algunos detalles de la definición anterior. En primer lugar vemos que las 4 secciones principales se engloban en un elemento <group> al que hemos asignado su propiedad checkableBehavior con valor “single“. Con esto indicamos que sólo pueda seleccionarse una de estas tres opciones al mismo tiempo (más tarde veremos como resaltar la opción seleccionada). A continuación se añaden dos opciones más dentro de un submenú al que asignamos su título con la propiedad android:title. Este título del submenú aparecerá en forma de cabecera de sección dentro del menú, incluyendo incluso una línea de división tras las tres opciones anteriores. Adicionalmente, en todas las opciones de menú indicamos su id (android:id), su icono (android:icon) y su título (android:title). En mi caso he utilizado por simplicidad el mismo icono en todas las opciones, pero por supuesto pueden ser distintos.
Como nota importante indicar que las opciones incluidas dentro de un submenú no es posible resaltarlas en la interfaz como sí ocurre con las opciones anteriores incluidas dentro del elemento group. Es posible que en futuras versiones de la librería de diseño se habilite esta posibilidad.
Fácilmente tenemos listo, estéticamente hablando, nuestro Navigation Drawer, con sus elementos, subtítulos y divisores. Ya todo lo que queda son pequeños arreglos.

Archivos de estilos styles.xml para todas las versiones


Styles.xml
Debemos crear un style para versiones inferiores a 19 y 21. Para ello haré un ejemplo de como crear un style para 19 usando Android Studio.
Click derecho en la carpeta /res/values/styles:
Escoger “Values resource file”
Elegir la opción de Version y luego apretar el botón “>>”
Escribir 19 en el campo de “Plataform API Level”, seguido de OK. Nos creará un nuevo archivo llamado , agregar lo siguiente dentro del mismo:
Replicar el proceso anterior, para versiones 21, agregar dentro del archivo lo siguiente:
El archivo colors.xml debería estar de la siguiente forma:
El archivo /res/values/attrs.xml debería ser de la siguiente forma (sino existe, crearlo):
Archivo String xml
Las imágenes e iconos que ocupan pueden descargarlas desde aquí.
El proyecto 100 % en funcionamiento está en mi github.




Read More »