Los menús en Android se utilizan para mostrar opciones adicionales a lo que la interfaz ofrece directamente. Además, ofrecen la posibilidad de asociarse directamente a un elemento. Desde Android 3.0 en adelante los menús toman una funcionalidad diferente ya que antiguamente se mostraban en la parte inferior de la pantalla, pasando ahora a mostrarse en la barra superior. De todas formas no todos los menús están situados en el mismo sitio, pudiendo distinguir varios tipos:
- Menú de opciones: es el más conocido de todos, ubicándose en la parte superior en la barra de actividad (si hubiese). Normalmente está representado por 3 puntos con posibilidad de estar acompañado también de iconos
- Menú contextual: aquel que está asociado a un elemento en concreto y aparece al pulsar de forma prolongada dicha vista
- Menú emergente: muy similar al anterior con la diferencia que está anclado a la vista que tiene asociada, apareciendo junto a ella
- Menú lateral: también llamado navigation view. Se trata del más avanzado de todos ya que su funcionamiento se basa en los fragments. Aparece deslizando el dedo de izquierda a derecha o al contrario
- Menu barra de herramientas. Sustituye al menú de opciones tradicional, con una funcionalidad prácticamente igual pero como se verá más adelante con muchas más posibilidades
Menú de opciones
Se trata del más conocido dentro de los menús, representado por tres puntos blancos situados en la barra de acciones. Para poder crear este tipo de menú hay que basarse en un archivo XML que represente el contenido. Para ello dentro de res –> menu se crea un archivo nuevo
<menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/menuElemento1" android:icon="@drawable/menu" android:title="Elemento 2" app:showAsAction="ifRoom"></item> <item android:title="Elemento 2" android:icon="@drawable/menu" android:id="@+id/menuElemento2"></item> </menu>
La etiqueta menu engloba todo el conjunto del archivo y las etiquetas ítem representan cada unas de las opciones. Dentro de estas las opciones title hace referencia al texto mostrado, la etiqueta icon al icono que se mostrará en caso de mostrarse directamente en la barra, la etiqueta id hace referencia a como se asociará en el .java y la etiqueta showAsAction hace referencia a si se mostrará como icono en en la barra en vez de en el menú. En el caso de querer representar un submenú, la etiqueta ítem tendrá que englobar una etiqueta menú
<item android:title="Elemento 3"> <menu> <item android:id="@+id/menuSub31" android:title="Subelemento 3-1" /> <item android:id="@+id/menuSub32" android:title="Subelemento 3-2" /> </menu> </item>
Una vez terminado el XML tan solo hace falta asociar el menú a la activity. Para ello se sobreescribe el método onCreateOptionMenu() cuyo parámetro menú será donde se ponga el menú creado. Para ello se utiliza un objeto MenuInflater
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_opciones, menu); return true; }
Desde este momento el menú aparecerá como elemento dentro de la barra de actividad. Para poder interactuar con el se sobreescribe el método onOptionItemSelected() evaluando la pulsación sobre las ids de los elementos
@Override public boolean onOptionsItemSelected(MenuItem item) { String aviso = null; switch (item.getItemId()) { case R.id.menuElemento1: aviso = "Has pulsado el elemento 1"; break; case R.id.menuElemento2: aviso = "Has pulsado el elemento 2"; break; case R.id.menuSub31: aviso = "Has pulsado el subelemento 3-1"; break; case R.id.menuSub32: aviso = "Has pulsado el subelemento 3-2"; break; } Toast.makeText(getApplicationContext(), aviso, Toast.LENGTH_SHORT).show(); return true; }
Menú contextual
Para poder crear un menú contextual, el primer paso es exactamente idéntico al caso anterior, crear el archivo XML que se quiera asociar al menú. Para este caso se utilizará la misma estructura de XML. El siguiente paso es registrar un menú para cada una de las vistas que queramos mediante el método registerForContextMenu pasa asociarlo y el método onCreateContextMenu(). En este caso se asociará el menú a un TextView
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); view = findViewById(R.id.text); registerForContextMenu(view); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { getMenuInflater().inflate(R.menu.menu_contextual,menu);
<item android:id="@+id/menuContextElemento2" android:icon="@drawable/menu" android:title="Elemento 2" android:actionLayout="@layout/switch_item"> </item>
Al tener un parámetro View e el método onCreateContextMenu podríamos asociar menús diferentes a vistas diferentes evaluando el origen de la llamada
@Override public boolean onOptionsItemSelected(MenuItem item) { String aviso=null; switch (item.getItemId()) { case R.id.menuElemento1: aviso = "Has pulsado el elemento 1"; break; case R.id.menuElemento2: aviso = "Has pulsado el elemento 2"; break; case R.id.menuSub31: aviso = "Has pulsado el subelemento 3-1"; break; case R.id.menuSub32: aviso = "Has pulsado el subelemento 3-2"; break; } Toast.makeText(getApplicationContext(), aviso, Toast.LENGTH_SHORT).show(); return true; }
Elementos avanzados en un menú
Además de poder asociar la propiedad chekeable a un ítem y evaluarla mediante isChecked, existe la posibilidad de asociar un elemento gráfico avanzado a un ítem de un menú como por ejemplo un swich. Para ello se utiliza la propiedad actionLayout donde se le indica el xml que pintará dicho elemento.
<item android:id="@+id/menuElemento2" android:icon="@drawable/menu" android:title="Elemento 2" android:actionLayout="@layout/switch_item"> </item>
El archivo que representa este layout simplemente es un componente swichView cuya id se utilizará para saber si esta o no activado
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Switch android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/switch_menu" android:layout_centerHorizontal="true" android:layout_centerVertical="true" /> </RelativeLayout>
Cuando se quiera evaluar este switch se tendrá que acceder asociar a un elemento del mismo tipo y ponerle un escuchador como cualquier otro elemento
switchMenu = (Switch) getMenu().findItem(R.id.menuElemento2).getActionView();
Menú emergente
También se le conoce como menú popup. Para poder utilizarlo se necesita el XML asociado y crear un objeto de tipo PopupMenu inflado con el xml correspondiente
view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { PopupMenu popup = new PopupMenu(getApplicationContext(), view2); MenuInflater inflater = popup.getMenuInflater(); inflater.inflate(R.menu.menu_pop, popup.getMenu()); popup.show(); } });
Para poder manejar las acciones sobre este tipo de menú se debe incluir el escuchador sobre el popupmenu.
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem menuItem) { String aviso = null; switch (menuItem.getItemId()) { case R.id.menuPopElemento1: aviso = "Has pulsado el elemento 1"; break; case R.id.menuPopElemento2: aviso = "Has pulsado el elemento 2"; break; } Toast.makeText(getApplicationContext(), aviso, Toast.LENGTH_SHORT).show(); return true; } });