En este articulo estudiaremos las características y el uso de la Action Bar (Barra de acción) en el desarrollo Android. Veremos su anatomía, como crear un archivo de diseño para ella, como ejecutar las acciones una vez presionado sus opciones y otras características relevantes.
Indice:
- Funciones del Action Bar
- Anatomía de la Action Bar
- Archivo de diseño de una Action Bar
- Programar eventos de una Action Bar
- Algunos trucos adicionales
¿Qué es la action Bar y para que funciona?
Para quienes tienen dispositivos móviles ya puede deducir algunas funciones de este maravilloso elemento. La Action Bar es un menú auxiliar de las aplicaciones Android, que se ubica en al parte superior de cada actividad. Digo de cada actividad, ya que es un elemento que por lo general es persistente.
Esta pequeña barra tiene enormes utilidades, como por ejemplo: Proveernos acceso rápido a las acciones mas comunes y solicitadas por los usuarios, organizar la navegación entre actividades(pestañas para swiping, expand and collapse, navigation drawers, etc), proporcionarnos un espacio donde diferenciar nuestra aplicación de otras aplicaciones( a través del título, iconos particulares y demás) y proyectar fácil acceso de las funcionalidades de la aplicación.
Anatomía de la Action Bar
La barra de acción se divide en cuatro partes fundamentales que debemos reconocer antes de empezar a programar sobre ella. Por lo que veremos la siguiente ilustración sobre su estructura:
Observemos la definición de cada segmento:
- Icono de la aplicación: Como ya hemos visto, en esta ubicación se proyecta el recurso drawable del icono de la aplicación. Por defecto se ha usado un icono predeterminado por los recursos de Android, pero es ideal darle vida a tu aplicación diseñando tu propia imagen, logo o distinción.
- View de control: Este espacio esta diseñado para insertar views que permitan acceder al contenido de la actividad con el fin de mejorar la navegación. Por lo general se usan Spinners, TextViews, SearchViews , etc., para controlar el contenido. Normalmente vemos un texto estático que visualiza el nombre de la aplicación.
- Despliegue de acciones: Este segmento contiene una lista de acciones que no son tan populares, pero pueden ser necesitadas en algún momento por el usuario para tener acceso de forma sencilla.
Archivo de diseño de la Action Bar
Comencemos con el código. Para experimentar el poder de la barra de acción vamos a crear una sencilla aplicación que nos permita entender como funciona este elemento.
Improvisaremos una Action Bar que provea las operaciones CRUD para los elementos de una base de datos. Para ello usaremos 5 acciones: Añadir, Editar, Eliminar, Buscar y Ajustes.
Lo primero que haremos será crear un nuevo proyecto con una actividad Main en blanco llamado Cruder.
Para añadir el diseño a la Action Bar necesitamos usar un archivo de diseño que contenga los nodos necesarios para generar las opciones. Pero eso no es problema para nosotros, ya que Android Studio autogeneró un archivo de recursos en la dirección main/res/menu
.
Si abres el archivo main.xml
verás el diseño de nuestra Action Bar que ha sido creada por defecto.
Veamos:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".Main" >
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
Esta vez no usamos ningún tipo de contenedor de la familia Layout, si no que empleamos un elemento contenedor llamado <menu>
. Este representa nuestra Action Bar y cada elemento <item>
se refiere a los botones de acción que usaremos. Por defecto Android Studio crea un ítem llamado action_settings
para manejar las preferencias de la aplicación.
Al abrir la previsualización (Preview) y es posible detallar como se vería la Action Bar con este diseño.
Los elementos <item>
tienen cinco atributos prioritarios que debemos establecer para darles forma, así que veamos sus definiciones:
id
: Representa la identificación de cada ítem para ser referenciado en nuestro archivoR.java
.title
: Es unstring
asignado para el título del botón.icon
: Aquí asignaremos el icono que representará la acción en la Action Bar . Recuerda usar una referencia hacia tus recursos drawables.showAsAction
: Este atributo permite establecer cuando y donde veremos nuestros botones de acción. Las opciones mas usadas sonifRoom
ynever
. La primera indica que si existe espacio disponible para nuestro ítem, entonces se visualizará. La segunda indica que nunca debe aparecer en la Action Bar, solamente en el despliegue de botones de poco uso(Action overflow).orderInCategory
: Es un valor entero que establece la preponderancia que tiene un ítem con respecto a otro. Lo que quiere decir que un ítem con categoría 1 es mas prioritario que uno en categoría 2.
Nuestro ejemplo
En base a este conocimiento, procederemos a crear nuestro propio menú. Como ya sabemos que son cinco Action Buttons, entonces elegiremos cuales de esos son los mas populares para los usuarios de nuestra aplicación.
A mi parecer, creo que la búsqueda y añadir un nuevo elemento a la base de datos es muy relevante, el resto de opciones no es tan frecuente usarlas. Tal vez tu lo consideres distinto y es valido que uses tus propios criterios, por lo que no nos complicaremos, ya que esta aplicación solo es de propósito educativo.
Una vez elegidos los que deseamos ver persistentemente en la actividad, procederemos a escribir el archivo de diseño.
Este quedaría de la siguiente forma:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".Main" >
<item android:id="@+id/add"
android:icon="@android:drawable/ic_menu_add"
android:title="@string/add"
android:orderInCategory="1"
android:showAsAction="ifRoom"/>
<item android:id="@+id/search"
android:icon="@android:drawable/ic_menu_search"
android:title="@string/search"
android:orderInCategory="2"
android:showAsAction="ifRoom"/>
<item android:id="@+id/edit"
android:title="@string/edit"
android:orderInCategory="3"
android:showAsAction="never"/>
<item android:id="@+id/delete"
android:title="@string/delete"
android:orderInCategory="4"
android:showAsAction="never"/>
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"
android:showAsAction="never" />
</menu>
¿Que puedes notar?... ¡exacto!, los ítems que dijimos que eran los mas importantes se les asigno en su atributo showAsAction
la opción ifRoom
, a los demás les asignamos never
.
¿Algo mas?...bueno, si aún no lo has visto, fíjate en los valores del atributo icon
para los botones que se mostrarán. Tienen referencias raras y Android Studio no muestra error alguno...¿por qué?
Se debe a que esos recursos drawables que estamos referenciando no son de nosotros, son del sistema como tal. Por eso usamos el namespace android:drawable
. Con eso declaramos que deseamos usar los iconos del sistema.
También hemos ubicado en orden prioritario nuestros action buttons desde 1 a 4. Para Ajustes usamos el índice 100 debido a que siempre será considerado la opción menos solicitada en una aplicación.
Para este diseño la previsualización quedó de la siguiente forma:
El botón de Añadir se ha mostrado primero que el de buscar debido a su prioridad. Al igual que en la sección de despliegue, primero está Editar y Eliminar que la opción Ajustes.
Programar los eventos de la Action Bar
Una vez diseñado el cuerpo de nuestra barra, procedemos a programar los eventos que puedan producirse sobre ella. Para ello disponemos de métodos callback especiales similares a los que poseen las actividades.
Inflar el menú de la Action Bar
En primer lugar encontramos a onCreateOptionsMenu()
. Si te fijas en el archivo Main.java
autogenerado por Android Studio, este método ya esta sobrescrito con algunas instrucciones por defecto. Este método es autoinvocado para inflar todo el código XML que tenemos en nuestro archivo de diseño.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
El método recibe como parámetro una instancia de tipo Menu
, equivalente al elemento XML <menu>
. Las instrucciones que se dan dentro de ese método son muy similares a las del método onCreate()
de las actividades.
Lo primero que se hace es obtener una referencia del MenuInflater
al cual esta relacionada la actividad. Este objeto es el encargado de inflar el código de los menús para combinarlo con la actividad. En la segunda instrucción se invoca al método inflate()
para inflar el archivo R.menu.main
.
Finalmente se retorna en true
para indicar que todo salió como se esperaba.
Programar los eventos de los action Buttons
Ahora usaremos el método onOptionsItemSelected()
para asignar las funciones a cada botón. Este método es autoinvocado cuando el usuario presiona un botón. Al igual que el método anterior también veremos que Android Studio lo ha sobrescrito:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
Como parámetro tiene un objeto del tipo MenuItem
el cual es el equivalente Java del nodo <item>
de XML. Para saber que botón ha sido presionado obtenemos su identificador con el método getItemId()
. Luego se usa el id
como entrada de una estructura switch
, donde habrá un caso por cada botón que exista.
Así que eliminaremos lo que Android Studio nos sobrescribió y pondremos las siguientes instrucciones:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add:
//metodoAdd()
info.setText("Se presionó Añadir");
return true;
case R.id.search:
//metodoSearch()
info.setText("Se presionó Buscar");
return true;
case R.id.edit:
//metodoEdit()
info.setText("Se presionó Editar");
return true;
case R.id.delete:
//metodoDelete()
info.setText("Se presionó Eliminar");
return true;
case R.id.action_settings:
//metodoSettings()
info.setText("Se presionó Ajustes");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Es recomendable poner métodos void
para ejecutar las acciones correspondientes a cada botón. Pero esta ocasión solo modificaremos el texto de un TextView
de prueba, asignándole el mensaje que corresponde a la opción seleccionada. En el caso default
del switch
delegaremos el comportamiento al supermétodo.
Finalmente el código de nuestra actividad principal quedaría de esta forma:
package TUPAQUETE.cruder;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class Main extends Activity {
private TextView info;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Obteniendo la intancia del textview
info =(TextView)findViewById(R.id.info);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add:
//metodoAdd()
info.setText("Se presionó Añadir");
return true;
case R.id.search:
//metodoSearch()
info.setText("Se presionó Buscar");
return true;
case R.id.edit:
//metodoEdit()
info.setText("Se presionó Editar");
return true;
case R.id.delete:
//metodoDelete()
info.setText("Se presionó Eliminar");
return true;
case R.id.action_settings:
//metodoSettings()
info.setText("Se presionó Ajustes");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Si todo ha salido muy bien, al ejecutar verías un resultado muy parecido al de la siguiente ilustración.
Hay que tener en cuenta que la sección Action overflow de la Action Bar se visualiza solo en los dispositivos que no tengan la tecla menú en su hardware. Si seleccionas algún AVD que represente un modelo que contenga la tecla menú, entonces debes presionarla para poder visualizar el despliegue de nuestras acciones secundarias.
Algunos trucos adicionales
A continuación te mostraré dos situaciones que tal vez puedas llegar a necesitar cuando estés desarrollando tus aplicaciones.
Ocultar/Mostrar la Action Bar
En ocasiones los desarrolladores desean ocultar la Action Bar para satisfacer alguna necesidad o reclamar más espacio y claridad para la navegación.
Resolver este inconveniente es muy sencillo y práctico, simplemente haremos uso de los métodos hide()
y show()
de la clase ActionBar
. Como su traducción lo indica, hide()
esconde la barra y show()
la muestra de nuevo.
Observemos ambos casos:
import android.app.ActionBar //Incluye la dependencia
...
//Obteniendo la instancia
ActionBar actionBar = getActionBar();
//Escondiendo la Action Bar
actionBar.hide();
...
//Mostrando de nuevo la Action Bar
actionBar.show();
Solo basta con acceder a la instancia de la barra con el método getActionBar()
de la clase Activity
.
Cambia el icono de la Action Bar
Este cambio es muy frecuente para la personalización de nuestras aplicaciones. Ya hemos visto que el icono de la Action Bar es el mismo icono de lanzamiento de los recursos de Android. Así que para cambiarlo debemos crear primero nuestro propio icono o logo y situarlo en la sección App Icon.
Si el icono será prestablecido cuando se inicia la aplicación, entonces podemos añadirlo de forma descriptiva al archivo del menú. Para asignar el icono usaremos el atributo android:logo
en la etiqueta <application>
del archivo AndroidManifiest.xml
. Su valor será la referencia de un recurso drawable que represente a nuestro logo. Veamos un ejemplo:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:logo="@drawable/logo"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
Esta indicación especifica que deseamos que este logo aparezca en la Action Bar una vez iniciada la aplicación. La siguiente ilustración muestra el uso de un logo personalizado.
Y finalizando, si deseas añadir el icono en tiempo de ejecución, entonces usa el método setIcon()
de la clase ActionBar
. Veamos como hacerlo:
ActionBar actionBar = getActionBar();
//Seteando el icono
actiobBar.setIcon(R.drawable.logo);
Con este sencillo método podemos acceder en tiempo real a nuestro recursos y asignar la imagen correspondiente. El parámetro que recibe setIcon()
es un entero que representa la referencia que tenemos en las carpetas drawables.