Menús en Android (I): Conceptos
básicos
En los tres siguientes temas nos vamos a centrar en la creación de
menús de opciones en sus diferentes variantes.
NOTA IMPORTANTE: En versiones anteriores a la 3 (API 11) los
menús aparecían en la parte inferior de la pantalla. Esto ha caído en
desuso tras la aparición de la Action Bar. En las versiones actuales,
los menús aparecerán por defecto en el menú desplegable de la action
bar en la parte superior derecha o en la propia app bar, si así se lo
indicamos.
En Android podemos encontrar 4 tipos diferentes de menús:
Menús Principales. Los más habituales, aparecen en la zona
superior de la pantalla. Sus opciones son acciones que permiten
trabajar con la pantalla, ya sea cambiando su aspecto o
intercambiándola por otra, etc.
Submenús. Son menús secundarios que se pueden mostrar al
pulsar sobre una opción de un menú principal. Muestran
subopciones dentro de la opción que lo abre.
Menús Contextuales. Útiles en muchas ocasiones, aparecen
en una ventana en el centro de la pantalla al realizar una
pulsación larga sobre algún elemento de la pantalla. A veces
aparecen también encima de la AppBar, tapándola y haciendo las
veces de ésta. Suele contener acciones que sirven para la
modificación o actuación sobre el/los elemento/s escogido/s.
Pop-Up Menús. Aparecen al realizar una pulsación sobre algún
elemento de la pantalla, debajo de éste. Suele contener acciones
propias para ese elemento.
En este primer tema veremos cómo trabajar con los dos primeros tipos
de menús. Como casi siempre, vamos a tener dos alternativas a la
hora de mostrar un menú en nuestra aplicación Android. La primera de
ellas mediante la definición del menú en un fichero XML, y la segunda
creando el menú directamente mediante código. En este tema
veremos ambas alternativas.
Veamos en primer lugar cómo crear un menú a partir de su definición
en XML. Los ficheros XML de menú se deben colocar en la carpeta
“res\menu” de nuestro proyecto y tendrán una estructura análoga a la
del siguiente ejemplo:
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
2 <item android:id="@+id/MnuOpc1" android:title="Opcion1"
3 android:icon="@android:drawable/ic_menu_preferences"></item>
4 <item android:id="@+id/MnuOpc2" android:title="Opcion2"
5 android:icon="@android:drawable/ic_menu_compass"></item>
6 <item android:id="@+id/MnuOpc3" android:title="Opcion3"
7 android:icon="@android:drawable/ic_menu_agenda"></item>
8 </menu>
Como vemos, la estructura básica de estos ficheros es muy sencilla.
Tendremos un elemento principal <menu> que contendrá una serie de
elementos <item> que se corresponderán con las distintas opciones
a mostrar en el menú. Estos elementos <item> tendrán a su vez
varias propiedades básicas, como su ID (android:id), su texto
(android:title) o su icono (android:icon). Los iconos utilizados
deberán estar por supuesto en las carpetas “res/drawable-…” de
nuestro proyecto (al final del documento encontrareis unos enlaces
donde podéis conseguir algunos iconos de menú Android gratuitos) o
bien utilizar alguno de los que ya vienen “de fábrica” con la plataforma
Android. En nuestro caso de ejemplo utilizaremos esta segunda
opción, por lo que haremos referencia a los recursos con el prefijo
“@android:drawable/…“. Si quisiéramos utilizar un recurso propio
escribiríamos directamente “@drawable/…” seguido del nombre del
recurso.
Una vez definido el menú en el fichero XML, tendremos que
implementar el evento onCreateOptionsMenu() de la actividad que
queremos que lo muestre. En este evento deberemos “inflar” el menú
de forma parecida a cómo ya hemos hecho otras veces con otro tipo
de layouts. Primero obtendremos una referencia al inflater mediante el
método getMenuInflater() y posteriormente generaremos la
estructura del menú llamando a su método inflate() pasándole
como parámetro el ID del menu definido en XML, que en nuestro caso
será R.menu.activity_main. Por último devolveremos el valor
true para confirmar que debe mostrarse el menú.
1 @Override
2 public boolean onCreateOptionsMenu(Menu menu) {
3 //Alternativa 1
4 getMenuInflater().inflate(R.menu.activity_main, menu);
5 return true;
6 }
Y ya hemos terminado, con estos sencillos pasos nuestra aplicación
ya debería mostrar sin problemas el menú que hemos construido,
aunque todavía nos faltaría implementar la funcionalidad de cada una
de las opciones mostradas.
Como vemos el menú aparecerá dentro del menú de overflow y
además, no aparecerán sus iconos. Importante aquí es el atributo
android:showAsAction. Este atributo indica si la opción de menú
se mostrará como botón de acción o como parte del menú de
overflow. Puede tomar los siguientes valores:
ifRoom. Se mostrará como botón de acción sólo si hay
espacio disponible.
withText. Se mostrará el texto de la opción junto al icono
en el caso de que éste se esté mostrando como botón de
acción.
never. Siempre se mostrará en el menú de overflow.
always. Siempre se mostrará como botón de acción. Este
valor puede provocar que los elementos se solapen si no hay
espacio suficiente para ellos.
Con este atributo podemos hacer que alguna de las opciones se vean
en la app bar y no en el menú de overflow. En este caso sólo se verá
su icono, a menos que se elija el valor ‘withText’.
Como hemos comentado antes, este mismo menú lo podríamos crear
directamente mediante código, también desde el evento
onCreateOptionsMenu(). Para ello, para añadir cada opción del
menú podemos utilizar el método add() sobre el objeto de
tipo Menu que nos llega como parámetro del evento. Este método
recibe 4 parámetros: ID del grupo asociado a la opción (veremos qué
es esto más adelante, por ahora utilizaremos Menu.NONE), un ID
único para la opción (que declararemos como constantes de la clase),
el orden de la opción (que no nos interesa por ahora, utilizaremos
Menu.NONE) y el texto de la opción. Por otra parte, el icono de cada
opción lo estableceremos mediante el método setIcon() pasándole
el ID del recurso. Veamos cómo quedaría el código utilizando esta
alternativa, que generaría un menú exactamente igual al del ejemplo
anterior:
1 private static final int MNU_OPC1 = 1;
2 private static final int MNU_OPC2 = 2;
3 private static final int MNU_OPC3 = 3;
4
5 //...
6
7 @Override
8 public boolean onCreateOptionsMenu(Menu menu) {
9 //Alternativa 2
10 menu.add(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion1")
11 .setIcon(android.R.drawable.ic_menu_preferences);
12 menu.add(Menu.NONE, MNU_OPC2, Menu.NONE, "Opcion2")
13 .setIcon(android.R.drawable.ic_menu_compass);
14 menu.add(Menu.NONE, MNU_OPC3, Menu.NONE, "Opcion3")
15 .setIcon(android.R.drawable.ic_menu_agenda);
16 return true;
17 }
Para añadir la opción a la app bar, en este caso se usa el método
setShowAsAction(int), donde el valor entero puede ser
SHOW_AS_ACTION_IF_ROOM, SHOW_AS_ACTION_ALWAYS o
SHOW_AS_ACTION_NEVER (por defecto) y cualquiera de las tres
constantes puede llevar un OR (‘|’) con la opción
SHOW_AS_ACTION_WITH_TEXT.
Construido el menú, la implementación de cada una de las opciones
se incluirá en el evento onOptionsItemSelected() de la actividad
que mostrará el menú. Este evento recibe como parámetro el item de
menú que ha sido pulsado por el usuario, cuyo ID podemos recuperar
con el método getItemId(). Según este ID podremos saber qué
opción ha sido pulsada y ejecutar unas acciones u otras. En nuestro
caso de ejemplo, lo único que haremos será modificar el texto de una
etiqueta (lblMensaje) colocada en la pantalla principal de la
aplicación.
1 @Override
2 public boolean onOptionsItemSelected(MenuItem item) {
3 switch (item.getItemId()) {
4 case R.id.MnuOpc1:
5 lblMensaje.setText("Opcion 1 pulsada!");
6 return true;
7 case R.id.MnuOpc2:
8 lblMensaje.setText("Opcion 2 pulsada!");;
9 return true;
10 case R.id.MnuOpc3:
11 lblMensaje.setText("Opcion 3 pulsada!");;
12 return true;
13 default:
14 return super.onOptionsItemSelected(item);
15 }
16 }
Ojo, el código anterior sería válido para el menú creado mediante
XML. Si hubiéramos utilizado la implementación por código java,
tendríamos que sustituir las constantes R.id.MnuOpcX por nuestras
constantes MNU_OPCX.
Con esto, hemos conseguido ya un menú completamente funcional. Si
ejecutamos el proyecto en el emulador comprobaremos cómo al pulsar
el botón de ‘menu de overflow‘ aparece el menú que hemos definido y
que al pulsar cada opción se muestra el mensaje de ejemplo.
Pasemos ahora a comentar los submenús. Un submenú no es más
que un menú secundario que se muestra al pulsar una opción
determinada de un menú principal. Los submenús en Android se
muestran en forma de lista emergente, que si tiene título será el texto
de la opción elegida en el menú principal. Como ejemplo, vamos a
añadir un submenú a la Opción 3 del ejemplo anterior, al que
añadiremos dos nuevas opciones secundarias. Para ello, bastará con
insertar en el XML de menú un nuevo elemento <menu> dentro del
item correspondiente a la opción 3. De esta forma, el XML quedaría
ahora como sigue:
1 <menu xmlns:android="http://schemas.android.com/apk/res/android" >
2 <item android:id="@+id/MnuOpc1" android:title="Opcion1"
3 android:icon="@android:drawable/ic_menu_preferences"></item>
4 <item android:id="@+id/MnuOpc2" android:title="Opcion2"
5 android:icon="@android:drawable/ic_menu_compass"></item>
6 <item android:id="@+id/MnuOpc3" android:title="Opcion3"
7 android:icon="@android:drawable/ic_menu_agenda">
8 <menu>
9 <item android:id="@+id/SubMnuOpc1"
10 android:title="Opcion 3.1" />
11 <item android:id="@+id/SubMnuOpc2"
12 android:title="Opcion 3.2" />
13 </menu>
14 </item>
15 </menu>
Si volvemos a ejecutar ahora el proyecto y pulsamos la opción 3 nos
aparecerá el correspondiente submenú con las dos nuevas opciones
añadidas. Lo vemos en la siguiente imagen:
Si la opción tres estuviera dentro del menú de overflow, se vería así:
Comprobamos como aparecen las dos nuevas opciones en la lista
emergente, pero vemos que en la primera alternativa no aparece título
alguno. Sin embargo en la segunda si aparece y el título de la lista se
corresponde con el texto de la opción elegida en el menú principal
(“Opcion3“).
Para conseguir esto mismo mediante código procederíamos de forma
similar a la anterior, con la única diferencia de que la opción de menú
3 la añadiremos utilizando el método addSubMenu()en vez
de add(), y guardando una referencia al submenú. Sobre el submenú
añadido insertaremos las dos nuevas opciones utilizando una vez más
el método add(). Vemos cómo quedaría:
1 //Alternativa 2
2 menu.add(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion1")
3 .setIcon(android.R.drawable.ic_menu_preferences);
4 menu.add(Menu.NONE, MNU_OPC2, Menu.NONE, "Opcion2")
5 .setIcon(android.R.drawable.ic_menu_compass);
6
7 SubMenu smnu = menu.
8 addSubMenu(Menu.NONE, MNU_OPC1, Menu.NONE, "Opcion3")
9 .setIcon(android.R.drawable.ic_menu_agenda);
10 smnu.add(Menu.NONE, SMNU_OPC1, Menu.NONE, "Opcion 3.1");
11 smnu.add(Menu.NONE, SMNU_OPC2, Menu.NONE, "Opcion 3.2");
En cuanto a la implementación de estas opciones de submenú no
habría diferencia con todo lo comentado anteriormente ya que también
se tratan desde el evento onOptionsItemSelected(),
identificándolas por su ID.
Por tanto, con esto habríamos terminado de comentar las opciones
básicas a la hora de crear menús y submenús en nuestras
aplicaciones Android. En el siguiente tema veremos algunas opciones
algo más avanzadas que, aunque menos frecuentes, puede que nos
hagan falta para desarrollar determinadas aplicaciones.
Si necesitáis iconos para mostrar en los menús aquí tenéis varios
enlaces con algunos gratuitos que podéis utilizar en vuestras
aplicaciones Android:
http://www.androidicons.com
http://www.glyfx.com/products/free_android2.html
Ejercicios
1. Haz una actividad que pregunte al usuario por su nombre y su edad.
Crea un menú con 2 opciones dentro del menú de overflow y otras dos
fuera de él. Las dos de afuera deben aparecer con icono y al menos
una también con texto (puede que no quepa, entonces para verlo pon
el móvil en horizontal). Una de las opciones de dentro deberá tener un
submenú con al menos 3 subopciones (admitirán iconos????). Haz
ahora que cada opción realice algo con la pantalla. Por ejemplo, que le
dé la vuelta al nombre, que le sume 1 a la edad, que haga aparecer un
texto en pantalla que diga: “Hala, qué viejo!”, etc.
2. Siguiendo con la app anterior, haz ahora que una de las opciones
haga que se cambie de actividad, pasándole el nombre y la edad y
estos datos deberán aparecer en pantalla de la forma que quieras.
Intenta poner en el menú de esta segunda activity una flecha de
‘volver atrás’ y que funcione, es decir, que si se pulsa, se vuelva a la
primera activity.