No es un bug, es una característica no documentada

lunes, 9 de noviembre de 2015

Programación multimedia. Menús

Antes de empezar hay que saber que a partir de la versión 3 de Android los menús han sido relegado a un segundo plano en sustitución de la ActionBar. De hecho a partir de la API 11 los menús definidos aparecerán en el menú desplegable de la ActionBar en lugar de en la sección inferior.

En Android hay tres tipos de menús:
  • Menús principales. Los más habituales, aparecen en la zona inferior de la pantalla al pulsar el botón menú del teléfono. 
  • Submenús. Son menús secundarios que se pueden mostrar al pulsar sobre una opción de un menú principal.
  • Menús contextuales. Son los que aparecen al mantener una pulsación larga en algún elemento de la pantalla.

Para mostrar un menú vamos a tener dos alternativas.
  • La primera es mediante la definición del menú en un fichero XML definido en la ruta res/menú
  • La segunda creándolo a través de código directamente.

Menús clásicos

Supongamos que queremos montar un menú con dos opciones, Configuración y Acerca de definiéndolo en XML.


Vamos a la ruta res/menú y abrimos el archivo que nos aparece por defecto. 



La estructura es muy sencilla. Hay un elemento principal, <menu>, que contiene varios elementos <ítem> que serán las opciones de nuestro menú.
Los <ítem> tendrán a su vez varias propiedades:
  • ID (android:id)
  • Texto (android:title)
  • Icono (android:icon) – Deberan estár en la carpeta res/drawable o usar alguno agregados de fábrica de la plataforma android referenciándolos como @android:drawable.

Nuestro código quedaría tal que así:


Una vez definido como queramos el XML hay que implementar el método onCreateOptionsMenu() en la actividad que queremos cargar el menú (si es la actividad principal es posible que esté incluido ya por defecto).

Lo que haremos aquí es “inflar” el menú con la clase MenuInflater.
Primero obtendremos una referencia al inflater mediante el método getMenuInflater() y luego generaremos la estructura del menú llamando a su inflate() pasando como parámetro el identificador del menú definido en XML (R.menu.activity_main por ejemplo), y devolveremos TRUE para confirmar que hay que mostrar el menú.

public boolean onCreateOptionsMenu(Menu menu){
       MenuInflater inflater = getMenuInflater();
       Inflater.inflate(Rmmenu.activity_main,menu);
       Return true;
}

Ahora bien, también lo podemos hacer directamente por código como hemos comentado antes, igualmente desde el evento onCreateOptionsMenu(). Lo que hay que hacer es añadir cada opción del menú con el método add() sobre el objeto Menu que recibamos como parámetro. Este método recibe cuatro parámetros:
  • ID del grupo asociado a la opción
  • ID único para la opción – declarado como constante en la clase
  • Orden de la opción
  • Texto de la opción.

En caso de que queramos establecer un icono usaremos el método setIcon() pasando el identificador del recurso.

private static final int MNU_OPC1 = 1;
private static final int MNU_OPC2 = 2;
private static final int MNU_OPC3 = 3;

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(Menu.NONE, MNU_OPC1, Menu.NONE, "Opción 1").setIcon(android.R.drawable.ic_menu_preferences);
    menu.add(Menu.NONE, MNU_OPC2, Menu.NONE, "Opcion 2").setIcon(android.R.drawable.ic_menu_info_details);
    return true;
}

Ahora, una vez que ya está construido el menú, si quieremos implementar cada una de las opciones lo haremos en el evento onOptionsItemSelected() de la actividad que mostrará el menú.
Recibe como parámetro el ítem del menú que ha sido pulsado por el usuario y cuyo id recuperamos con el método getItemId(). Gracias a este identificador sabremos que opción ha sido pulsada y ejecutaremos una acción u otra.
Por ejemplo, sacar un Toast indicando que opción se ha pulsado.

public boolean onOptionsItemSelected(MenuItem item) {
    switch(item.getItemId()){
        case MNU_OPC1:
            Toast.makeText(getApplicationContext(), "Opcion 1", Toast.LENGTH_SHORT).show();
            return true;
        case MNU_OPC2:
            Toast.makeText(getApplicationContext(), "Opcion 1", Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Es decir, un menú se visualizaría de la siguiente forma (en una API superior a 11, que conste).

Menús contextuales

Este tipo de menús siempre va asociado a un control concreto de la pantalla y se muestra al realizar una pulsación larga sobre éste. Suele mostrar opciones  específicas de ese elemento, como por ejemplo eliminar un ítem de un listbox, o eliminar toda la colección.

Vamos a hacer un ejercicio sencillo para explicar su creación. Crearemos un proyecto nuevo con un menú contextual sobre un TextView con las opciones de Huesca, Zaragoza y Teruel. Al pulsar sobre Huesca el mensaje del TextView cambiará a fatos, con Zaragoza cambiará a cheposos y con Teruel cambiará a ababoles (en serio, ¿cómo se llaman los de Teruel?).

Lo primero será añadir un menú contextual que se muestre al pulsar sobre el TextView. En el método onCreate() asociamos la etiqueta a un menú llamando a registerForContextMenu().

TextView lblPregunta;

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_menu_contextual);
    lblPregunta = (TextView)findViewById(R.id.lblPregunta);
    registerForContextMenu(lblPregunta);
}

Ahora definimos un menú llamado menu_aragon en la carpeta res/menu


Ahora sobrescribimos en nuestra actividad el encargado de construir los menús contextuales, onCreateContextMenu(), que a diferencia del onCreateOptionsMenu() se llamará cada vez que queramos mostrar un menú contextual en vez de una vez al iniciar la aplicación.

Inflaremos el menú XML que hayamos creado con las distintas opciones, quedando de la siguiente manera:

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo){
    super.onCreateContextMenu(menu, v, menuInfo);

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_aragon, menu);
}

Y para finalizar implementamos el evento onContextItemSelected() para indicar que acciones realizar dependiendo de la opción elegida.

public boolean onContextItemSelected(MenuItem item){

    switch(item.getItemId()){
        case R.id.huesca:
            lblPregunta.setText("¡¡¡Fato!!!");
            return true;
        case R.id.zaragoza:
            lblPregunta.setText("¡¡¡Cheposo!!!");
            return true;
        case R.id.teruel:
            lblPregunta.setText("Mmmm... ¡¡¡ababoles!!!");
            return true;
        default:
            return super.onContextItemSelected(item);
    }
}

Y si lo ejecutamos podemos ver como se despliega y se modifica el TextView


0 comentarios:

Publicar un comentario