Menús

De MediaWiki
Saltar a: navegación, buscar

Introducción

  • Nesta unidade imos ver como xestionar menús, submenús e menú contextuais.
  • A seguinte imaxe amosa os menús na Action Bar da aplicación

Actionbar.png

  • 1: Icona da App e nome
  • 2: Dúas iconas de menús da aplicación
  • 3: Menú OverFlow que equivale ao botón Menú da Botonera.
  • Os menús poden poñerse na Action Bar dende a versión 3.0 de Android.


  • Esta barra pasa a chamarse AppBar a partires da versión Android 5 (API 21).


  • Para versións anteriores á 3.0 os menús víanse como na parte inferior da seguinte imaxe:

Options menu.png


  • A seguinte imaxe amosa 3 botóns de menú na Barra de Acción e o menú Overflow

Actionbar-item-withtext.png


  • Nesta imaxe vese como un dos menús da action bar ten submenús:

Actionbar-shareaction2x.png



  • Finalmente as seguintes imaxes amosan Menús Contextuais
    • Flotantes (esquerda)
    • ou na barra de accións (dereita)

Menu-context.png


Menús e submenús básicos

  • Indicar que podemos consultar o tamaño recomendado das iconas que van na AppBar neste enlace.
  • Podemos obter iconas no sitio web: http://www.iconarchive.com/ (intentar utilizar os que teñan licenza free).


  • Imos realizar unha aplicación con 3 menús (un deles con submenús e outro cunha icona na Barra de Acción).
  • Antes imos ver distintas casuísticas:


  • Se queremos que a ActionBar (AppBar a partires da versión API 21):
  • Teña o mesmo aspecto en todas as versións de Android.
  • Posibilidade de facer uso da interface de usuario Material Design (introducido a partires da API 21).
Teremos que facer uso das bibliotecas de compatibilidade e facer que a nosa activity derive de AppCompactActivity.
Ao facelo teremos que cambiar o deseño por un de tipo AppCompact.
Podedes consultar como facelo neste enlace: http://wiki.cifprodolfoucha.es/index.php?title=PDM_UD1_Bibliotecas_de_compatibilidade




Recursos Implicados

  • Os menús defínense nun recurso xml en res/menu/nome_ficheiro.xml


  • Dito recurso terá coma elementos:
    • <menu>: elemento raíz. Contén <item> e <group>
    • <item>: representa un elemento de menú.
      • Tería que ter un elemento <menu> dentro de <item> para crear un submenú.


  • Arrastrade dous 'menuitem' e cambiade as súas propiedades:
  • id: mniPrimeiro
  • Texto: Primeiro
  • id:mniSegundo
  • Texto: Segundo
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:app="http://schemas.android.com/apk/res-auto"
  3.    xmlns:android="http://schemas.android.com/apk/res/android">
  4.  
  5.     <item
  6.        android:id="@+id/mniPrimeiro"
  7.        android:title="Primeiro"
  8.        />
  9.     <item
  10.        android:id="@+id/mniSegundo"
  11.        android:title="Segundo"></item>
  12. </menu>


  • Agora comentaremos algúns dos atributos que podemos cambiar.
Lembrar que o podemos facer graficamente ou directamente no editor na vista XML.
  • Atributo android:showAsAction (se a activity deriva da clase Activity):
Atributo app:showAsAction (se a activity deriva da clase AppCompactActivity)
IMPORTANTE: Se temos importada a librería de compatibilidade AppCompactActivity no build.gradle nos vai a obrigar a empregar esta opción (app:) e polo tanto teremos que facer que a activity derive de AppCompactActivity.
PDM menu 11.jpg
  • Pode ter os seguintes valores:
    • never: nunca amosa o item de menú na barra de acción.
    • ifRoom: se hai espazo na barra de acción o amosa.
    • always: amosa sempre na barra de acción.
    • withText: se temos unha icona, por defecto non amosa o texto. Se queremos que amose os dúos poñeremos este valor.
    • collapseActionView: cando a acción dun elemento de menú (declarada coma android:actionLayout ou android:actionViewClass) é plegable. Dispoñible apartires da versión API 14. Exemplo de uso neste enlace.


  • Atributo android:orderInCategory="Nº Enteiro":
Despois de premer no deseñador de Android Studio na opción 'View all attributes':
PDM menu 12.jpg
Se hai varios ítems indica cal aparecerá primeiro, segundo, etc. Se todos teñen o mesmo valor ou non se pon valor ningún, entón aparecen na orde na que son creados, de esquerda a dereita e de arriba-abaixo.


  • Os elementos de menú que aparecen na barra, xa non aparecen no menú o premer o botón Menú ou "OverFlow", aínda que estean nun group, como se pode apreciar nas imaxes de abaixo.
  • Os valores pódense combinar có caracter ‘|’.


  • O atributo android:onClick funciona igual que nas vistas do recurso xml do Layout.



  • EXEMPLO DE MENÚ NA BARRA DE ACCIÓN CON SUBMENUS
  • A seguinte imaxe, obtense co seguinte recurso xml.

Android 2014 U5 01 Menus 09.jpg


Lembra que xa vimos como engadir novos recursos gráficos cando vimos o ImageView.


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:app="http://schemas.android.com/apk/res-auto"  xmlns:android="http://schemas.android.com/apk/res/android">
  3.  
  4.     <item
  5.        android:id="@+id/itemAbrir"
  6.        android:icon="@drawable/open32"
  7.        android:showAsAction="ifRoom"
  8.        android:title="Abrir"
  9.        android:titleCondensed="Abrir">
  10.         <menu>
  11.             <item
  12.                android:id="@+id/itemDoc"
  13.                android:title="Documento"
  14.                android:titleCondensed="Doc."/>
  15.             <item
  16.                android:id="@+id/itemIma"
  17.                android:title="Imaxes"
  18.                android:titleCondensed="Imax."/>
  19.             <item
  20.                android:id="@+id/itemAudio"
  21.                android:title="Audio"
  22.                android:titleCondensed="Audio"/>
  23.         </menu>
  24.     </item>
  25.     <item
  26.        android:id="@+id/itemNovo"
  27.        android:icon="@drawable/close32"
  28.        android:showAsAction="ifRoom"
  29.        android:title="Novo documento"
  30.        android:titleCondensed="N.Doc.">
  31.     </item>
  32.     <item
  33.        android:id="@+id/itemSair"
  34.        android:icon="@drawable/exit32"
  35.        android:showAsAction="ifRoom"
  36.        android:title="Saír"
  37.        android:titleCondensed="Saír">
  38.     </item>
  39.  
  40. </menu>
  • Liñas 6,27,34: Indican o recurso drawable que deben amosar. Estas imaxes deben estar na carpeta /res/drawableXXXXX correspondentes.
  • Liñas 7,28,35: Indican que se hai espazo na barra de acción que amosen eses ítems que teñen ese atributo.
  • Liñas 9,30,37: O atributo android:titleCondensed usarase cando o valor de android:title sexa demasiado longo.
  • Liñas 10-23: Para crear submenús dentro dun menú, volvemos a crear a entrada <menu> dentro de <item>


Agrupamentos

  • Outro elemento que pode ir dentro do elemento <menu>:
    • <group>: un grupo é un conxunto de elementos que teñen certas características.
      • Amosar ou ocultar todos os elementos: setGroupVisible()
      • Habilitar ou deshabilitar todos os elementos: setGroupEnabled()
      • Facer que todos os ítems do group poidan ser presentados en forma de checkbox: setGroupCheckable()
        • Podemos facer que un elemento sexa chequeable usando o atributo android:checkable no elemento <item> ou o
        • group enteiro con 'android:checkableBehavior no elemento <group>.
        • O atributo android:checkableBehavior pode ter as seguintes opcións:
          • single: só un elemento do grupo pode ser checkeado (radiobuttons).
          • all: todos os elementos poden ser checkeados (checkboxs).
          • none: ningún elemento é seleccionable.
        • Se non poñemos nada, os elementos do <group> aparecen como os demais.


  • A seguinte imaxe, ten asociado o seguinte XML.
  • Observar que na barra de acción non collen todos os menús.
  • Observar que hai dous menús (Modo Lectura e Modo Gravación) que poden ser marcados os dous.


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android">
  3.  
  4.     <item
  5.        android:id="@+id/itemAbrir"
  6.        android:icon="@drawable/open32"
  7.        android:showAsAction="always"
  8.        android:title="Abrir"
  9.        android:titleCondensed="Abrir">
  10.         <menu>
  11.             <item
  12.                android:id="@+id/itemDoc"
  13.                android:title="Documento"
  14.                android:titleCondensed="Doc."/>
  15.             <item
  16.                android:id="@+id/itemIma"
  17.                android:title="Imaxes"
  18.                android:titleCondensed="Imax."/>
  19.             <item
  20.                android:id="@+id/itemAudio"
  21.                android:title="Audio"
  22.                android:titleCondensed="Audio"/>
  23.         </menu>
  24.     </item>
  25.     <item
  26.        android:id="@+id/itemNovo"
  27.        android:icon="@drawable/close32"
  28.        android:showAsAction="ifRoom"
  29.        android:title="Novo documento"
  30.        android:titleCondensed="N.Doc.">
  31.     </item>
  32.     <item
  33.        android:id="@+id/itemSair"
  34.        android:icon="@drawable/exit32"
  35.        android:showAsAction="ifRoom"
  36.        android:title="Saír"
  37.        android:titleCondensed="Saír">
  38.     </item>
  39.  
  40.     <group
  41.        android:id="@+id/mgrpModos"
  42.        android:checkableBehavior="all" >
  43.         <item
  44.            android:id="@+id/ModoLect"
  45.            android:showAsAction="ifRoom"
  46.            android:title="Modo Lectura"
  47.            android:titleCondensed="M.Lect.">
  48.         </item>
  49.         <item
  50.            android:id="@+id/ModoRecord"
  51.            android:showAsAction="ifRoom"
  52.            android:title="Modo Grabación"
  53.            android:titleCondensed="M.Grab">
  54.         </item>
  55.     </group>
  56.  
  57. </menu>
  • Liñas 35,45,51: Observar como estes ítems non se amosan na barra de acción porque non teñen espazo.
  • Liñas 40-55: Observar como hai un agrupamento de ítems e na liña 42 indícase que todos eles son "chequeables".

Lanzar e procesar o menú

  • Para lanzar o menú debemos cambiar o menú que ten asinada unha determinada Activity e para iso temos que sobrescribir o método onCreateOptionsMenu().
  • O que facemos en "inflar" o xml asociado ao menú (Liña 4) do mesmo xeito que se fai cando se
  1.     @Override
  2.     public boolean onCreateOptionsMenu(Menu menu) {
  3.         // Inflate the menu; this adds items to the action bar if it is present.
  4.         getMenuInflater().inflate(R.menu.menu_ud04_01_menus, menu);
  5.         return true;
  6.     }


  • Cando se preme un ítem dun menú lánzase o evento onOptionsItemSelected e para procesar ese ítem sobrescribir o método onOptionsItemSelected(MenuItem item).
  1.         @Override
  2.         public boolean onOptionsItemSelected(MenuItem item) {
  3.                 // Handle action bar item clicks here. The action bar will
  4.                 // automatically handle clicks on the Home/Up button, so long
  5.                 // as you specify a parent activity in AndroidManifest.xml.
  6.  
  7.                 int id = item.getItemId();
  8.                 if (id == R.id.itemAbrir) {
  9.                         return true;
  10.                 }
  11.                 return super.onOptionsItemSelected(item);
  12.           }
  • Este método devolve un boolean:
    • true: se procesamos un elemento do menú (return true).
    • false: se queremos que o evento siga 'propagándose' polo resto da xerarquía de views do Activity.

Caso práctico

Se non o temos creado antes, crearemos un novo paquete de nome: Menus como un subpaquete do teu paquete principal.



  • Dentro do paquete Menus crear unha nova 'Empty Activity' de nome: UD04_01_Menus de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.



Nota: Nas imaxes aparece como label da activity: 'U5_01_XXXX'. Non fagades caso e a vos debería saír: UD04_01_Menus.



As imaxes dos menús

  • Neste caso colocouse en cada recurso res/drawable a imaxe da cara:

PDM menu 15.jpg


Recursos XML

  • O xml do Layout:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    xmlns:app="http://schemas.android.com/apk/res-auto"
  4.    xmlns:tools="http://schemas.android.com/tools"
  5.    android:layout_width="match_parent"
  6.    android:layout_height="match_parent"
  7.    tools:context=".Menus.UD04_01_Menus">
  8.  
  9.     <TextView
  10.        android:id="@+id/tvTexto_UD04_01_Menus"
  11.        android:layout_width="wrap_content"
  12.        android:layout_height="wrap_content"
  13.        android:layout_marginBottom="8dp"
  14.        android:layout_marginEnd="8dp"
  15.        android:layout_marginStart="8dp"
  16.        android:layout_marginTop="8dp"
  17.        android:text="TextView"
  18.        android:textSize="24sp"
  19.        app:layout_constraintBottom_toBottomOf="parent"
  20.        app:layout_constraintEnd_toEndOf="parent"
  21.        app:layout_constraintStart_toStartOf="parent"
  22.        app:layout_constraintTop_toTopOf="parent" />
  23. </android.support.constraint.ConstraintLayout>


  • Creamos un XML có texto das opcións de menú en /res/values/ de nome strings_mnu_ud04_01_menus:
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <resources>
  3.     <string name="str_mniItem1_UD04_01_Menus">Opción 1</string>
  4.     <string name="str_mniItem2_UD04_01_Menus">Opción 2</string>
  5.     <string name="str_mnuItem3_UD04_01_Menus">Opción 3- Submenús</string>
  6.     <string name="str_mniItem3_1_UD04_01_Menus">Opción 3- Submenú 1 - Calculadora</string>
  7.     <string name="str_mniItem3_2_UD04_01_Menus">Opción 3- Submenú 2 - Saír</string>
  8.  
  9. </resources>


  • O xml do menú (modificamos o recurso XML creado por defecto en /res/menu/...)
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:app="http://schemas.android.com/apk/res-auto"
  3.    xmlns:android="http://schemas.android.com/apk/res/android">
  4.  
  5.     <item
  6.        android:id="@+id/mniItem1_04_01_Menus"
  7.        android:icon="@drawable/ic_action_emo_basic"
  8.        android:orderInCategory="100"
  9.        app:showAsAction="always"
  10.        android:title="@string/str_mniItem1_UD04_01_Menus"/>
  11.     <item
  12.        android:id="@+id/mniItem2_04_01_Menus"
  13.        android:orderInCategory="100"
  14.        app:showAsAction="never"
  15.        android:title="@string/str_mniItem2_UD04_01_Menus"/>
  16.     <item
  17.        android:id="@+id/mnuItem_3_04_01_Menus"
  18.        android:orderInCategory="100"
  19.        app:showAsAction="never"
  20.        android:title="@string/str_mnuItem3_UD04_01_Menus">
  21.         <menu>
  22.             <item
  23.                android:id="@+id/mniItem3_1_04_01_Menus"
  24.                android:title="@string/str_mnuItem3_1_UD04_01_Menus"/>
  25.             <item
  26.                android:id="@+id/mniItem3_2_04_01_Menus"
  27.                android:title="@string/str_mniItem3_2_UD04_01_Menus"/>
  28.         </menu>
  29.     </item>
  30. </menu>
  • Liñas 8,13,18: Observar como todos os ítems teñen o mesmo valor para a ser ordenados.
    • Que o participante no curso probe a cambiar o terceiro ítem a un valor de 99.
  • Liñas 9,14,19: Observar como o primeiro ítem indica always e os demais never á hora de amosar o menú na barra de acción.

O código da Activity

  1. package es.cursoandroid.cifprodolfoucha.aprendiendo.Menus;
  2.  
  3. import android.content.Intent;
  4. import android.os.Bundle;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.view.Menu;
  7. import android.view.MenuItem;
  8. import android.widget.TextView;
  9. import android.widget.Toast;
  10.  
  11. import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
  12.  
  13. public class UD04_01_Menus extends AppCompatActivity {
  14.  
  15.     @Override
  16.     protected void onCreate(Bundle savedInstanceState) {
  17.         super.onCreate(savedInstanceState);
  18.         setContentView(R.layout.activity_ud04_01__menus);
  19.     }
  20.  
  21.  
  22.     @Override
  23.     public boolean onCreateOptionsMenu(Menu menu) {
  24.         // Inflate the menu; this adds items to the action bar if it is present.
  25.         getMenuInflater().inflate(R.menu.menu_ud04_01_menus, menu);
  26.         return true;
  27.     }
  28.  
  29.  
  30.     @Override
  31.     public boolean onOptionsItemSelected(MenuItem item) {
  32.         // Handle action bar item clicks here. The action bar will
  33.         // automatically handle clicks on the Home/Up button, so long
  34.         // as you specify a parent activity in AndroidManifest.xml.
  35.  
  36.         TextView tv = (TextView) findViewById(R.id.tvTexto_UD04_01_Menus);
  37.         Toast.makeText(getApplicationContext(), "Pulsado elemento: " + item.getTitle().toString(), Toast.LENGTH_SHORT).show();
  38.  
  39.         switch (item.getItemId()) {
  40.             case R.id.mniItem1_04_01_Menus:
  41.                 tv.setText("Quedarei con esta cara de sorriso cando remate esta tarefa");
  42.                 return true;
  43.  
  44.             case R.id.mniItem2_04_01_Menus:
  45.                 tv.setText("A opción 2 non ten nada asignado");
  46.                 return true;
  47.  
  48.             case R.id.mniItem3_1_04_01_Menus:
  49.                 Intent intent = new Intent();
  50.                 intent.setClassName("com.android.calculator2", "com.android.calculator2.Calculator");
  51.                 startActivity(intent);
  52.                 return true;
  53.  
  54.             case R.id.mniItem3_2_04_01_Menus:
  55.                 finish();
  56.                 return true;
  57.             default:
  58.                 return super.onOptionsItemSelected(item);
  59.  
  60.         }
  61.     }
  62.  
  63.     /**
  64.      * Método que se chama cando a activity se pecha.
  65.      */
  66.     public void finish() {
  67.         super.finish();
  68.     }
  69.  
  70.  
  71. }
  • Liña 37: Recollemos o título do ítem pulsado.
  • Liñas 42,46,52,56: devolver true no caso de procesar cada un dos ítems.
  • Liña 58: Se non se procesou o ítem chamar ao pai, que vai devolver false por defecto.


  • Se na definición de cada ítem se houbera usado o atributo android:onClick entón teríamos que crear en java os métodos correspondentes do mesmo xeito que se fai cando se usa ese atributo nun Layout.

Menús contextuais

  • Pódense crear sobre calquera elemento View, pero normalmente vanse usar con ListView e GridView.*
  • Existen dúas formas de implantar este tipo de menús:
  • Menú contextual flotante:
  • O menú aparece cando o usuario prema durante un tempo longo un elemento e aparece unha lista.

Android 2014 U5 02 MenusContextuais 01.jpg


Para crear este tipo de menú:

  • O View que queira usalo ten que ser asociado ao mesmo chamando o método registerForContextMenu pasando o obxecto View.
  • Se todos os elementos do ListView / GridView teñen o mesmo menú contextual, se pode pasar como parámetro o ListView / GridView.
  • Por exemplo (isto se fai no método onCreate): registerForContextMenu(lista);
    • Sendo lista a referencia a unha ListView.



  • Implantar o método onCreateContextMenu() na Activity / Fragment.
    • Este método será chamado de forma automática cando o usuario preme durante un tempo o elemento (View) asociado o ContextMenu.
    • O que fai este método é amosar o menú contextual creado por nós previamente.
  1. @Override
  2. public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
  3.     super.onCreateContextMenu(menu, v, menuInfo);
  4.     MenuInflater inflater = getMenuInflater();
  5.     inflater.inflate(R.menu.context_menu, menu);
  6. }
  • Lembrar que o MenuInflater serve para pasar dun arquivo XML (o menú contextual definido por nós) a obxectos MenuItems.
  • Fixarse que un dos parámetros é o view sobre o que queremos amosar o menú contextual. Se temos varios rexistrados (registerForContextMenu) serviranos para saber de cal vimos.


  • Implantar o método onContextItemSelected() ao que se chama de forma automática cando se selecciona algo do menú contextual
  1.         @Override
  2.         public boolean onContextItemSelected(MenuItem item) {
  3.                 AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
  4.                 switch (item.getItemId()) {
  5.                 case R.id.edit:
  6.                         // editNote(info.id); Lanzaríamos unha activity obtendo o texto do elemento da lista a partires do seu id ou coa súa posicición (info.position)
  7.                         return true;
  8.                 case R.id.delete:
  9.                         // deleteNote(info.id); Borraríamos o elemento da lista en base ao seu id ou coa súa posicición (info.position)
  10.                         return true;
  11.                 default:
  12.                         return super.onContextItemSelected(item);
  13.                 }
  14.         }
  • Liña 3. Do ítem pulsado recibimos información extra, entre outras, o "id" e a "posición" do ítem do adaptador sobre o que se pulsou durante un tempo para crear o menú contextual.
    • Ese "id" e "posición" son recollidos na variable info de tipo AdapterContextMenuInfo.
  • Liña 4: fixarse que é item.getItemId() para obter referencia ao id do menú contextual que foi seleccionado. Non confundir co id do elemento do adaptador sobre o que foi creado ese menú contextual.
  • O resto funciona igual que non menú básico.


  • Menú de modo acción contextual:
  • Neste caso, o menú aparece nunha barra de acción contextual na parte superior da pantalla (só dispoñible a partires da versión 3.0 API11).Android 2014 U5 02 MenusContextuais 02.jpg

Menú contextual: Caso Práctico

Se non o temos creado antes, crearemos un novo paquete de nome: Menus como un subpaquete do teu paquete principal.



  • Dentro do paquete Menus crear unha nova 'Empty Activity' de nome: UD04_02_Menus de tipo Launcher e sen compatibilidade.
Modifica o arquivo AndroidManifiest.xml e engade unha label á activity como xa vimos na creación do proxecto base.



  • Neste caso vanse crear dous menús contextuais distintos:
    • un para unha etiqueta (TextView)
    • e outro para unha lista (ListView).

Menú contextual: O XML do Layout

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.    xmlns:app="http://schemas.android.com/apk/res-auto"
  4.    xmlns:tools="http://schemas.android.com/tools"
  5.    android:layout_width="match_parent"
  6.    android:layout_height="match_parent"
  7.    tools:context=".Menus.UD04_02_Menus">
  8.  
  9.     <TextView
  10.        android:id="@+id/tvTexto_UD04_02_Menus"
  11.        android:layout_width="wrap_content"
  12.        android:layout_height="wrap_content"
  13.        android:layout_marginEnd="8dp"
  14.        android:layout_marginStart="8dp"
  15.        android:layout_marginTop="8dp"
  16.        android:text="Hello World"
  17.        android:textSize="18sp"
  18.        app:layout_constraintEnd_toEndOf="parent"
  19.        app:layout_constraintStart_toStartOf="parent"
  20.        app:layout_constraintTop_toTopOf="parent" />
  21.  
  22.     <ListView
  23.        android:id="@+id/lvFroitas_UD04_02_Menus"
  24.        android:layout_width="0dp"
  25.        android:layout_height="169dp"
  26.        android:layout_marginEnd="8dp"
  27.        android:layout_marginStart="8dp"
  28.        android:layout_marginTop="16dp"
  29.        app:layout_constraintEnd_toEndOf="parent"
  30.        app:layout_constraintHorizontal_bias="1.0"
  31.        app:layout_constraintStart_toStartOf="parent"
  32.        app:layout_constraintTop_toBottomOf="@+id/tvTexto_UD04_02_Menus" />
  33. </android.support.constraint.ConstraintLayout>

Menú contextual: O XML dos menús contextuais

  • Imos crear dous recursos xml para cada un dos menús contextuais distintos que temos segundo premamos sobre un TextView ou sobre un ListView.
  • Poderían ser o mesmo menú contextual, pero así aprendemos que estes poden ser distintos en función da View ao que se asocien.

PDM MenusContextuais 10.jpg



  • O xml de /res/menu/menu_ud04_02_context_etiqueta.xml
Nota: O Android Studio seguramente vos dirá que existe un erro na liña android:showAsAction e que deberedes cambialo por 'app:showAsAction'. Non lle fagades caso Ese aviso aparece debido a que tedes importado a librería de compatibilidade v7 nalgunha outra práctica. Soamente sería necesario se a activity derivase da clase AppCompactActivity como fixemos na práctica anterior.


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android">
  3.  
  4.     <item
  5.        android:id="@+id/mniItem1_04_02_context_etiq"
  6.        android:showAsAction="withText"
  7.        android:title="TextView opción 1">
  8.     </item>
  9.     <item
  10.        android:id="@+id/mniItem2_04_02_context_etiq"
  11.        android:showAsAction="withText"
  12.        android:title="TextView opción 2">
  13.     </item>
  14.  
  15. </menu>


  • O xml de /res/menu/menu_ud04_02_context_lista.xml
Nota: O Android Studio seguramente vos dirá que existe un erro na liña android:showAsAction e que deberedes cambialo por 'app:showAsAction'. Non lle fagades caso Ese aviso aparece debido a que tedes importado a librería de compatibilidade v7 nalgunha outra práctica. Soamente sería necesario se a activity derivase da clase AppCompactActivity como fixemos na práctica anterior.
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <menu xmlns:android="http://schemas.android.com/apk/res/android" >
  3.  
  4.     <item
  5.        android:id="@+id/mniItemBorrar_ud04_02_context_lista"
  6.        android:showAsAction="withText"
  7.        android:title="Borrar">
  8.     </item>
  9.     <item
  10.        android:id="@+id/mniItemDuplicar_ud04_02_context_lista"
  11.        android:showAsAction="withText"
  12.        android:title="Duplicar">
  13.     </item>
  14. </menu>


  • Observar que nos dous ficheiros xml cada item ten asociado un "id", para logo ser identificado o ítem cando sexa procesado no código.

Menú contextual: o código Java da aplicación

  1. package es.cursoandroid.cifprodolfoucha.aprendiendo.Menus;
  2.  
  3. import android.app.Activity;
  4. import android.os.Bundle;
  5. import android.view.ContextMenu;
  6. import android.view.MenuInflater;
  7. import android.view.MenuItem;
  8. import android.view.View;
  9. import android.widget.AdapterView;
  10. import android.widget.ArrayAdapter;
  11. import android.widget.ListView;
  12. import android.widget.TextView;
  13. import android.widget.Toast;
  14.  
  15. import java.util.ArrayList;
  16. import java.util.Arrays;
  17.  
  18. import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
  19.  
  20. public class UD04_02_Menus extends Activity {
  21.  
  22.  
  23.     private void rexistarMenusEmerxentes(){
  24.  
  25.         TextView tv = findViewById(R.id.tvTexto_UD04_02_Menus);
  26.         registerForContextMenu(tv);
  27.  
  28.         ListView lv = findViewById(R.id.lvFroitas_UD04_02_Menus);
  29.         registerForContextMenu(lv);
  30.     }
  31.  
  32.     private void engadirDatosLista(){
  33.         String[] froitas = new String[] { "Laranxa", "Mango", "Ameixa" };
  34.         ArrayList<String> alFroitas = new ArrayList<String>();
  35.  
  36.         alFroitas.addAll(Arrays.asList(froitas));
  37.  
  38.         ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, alFroitas);
  39.         adaptador.setDropDownViewResource(android.R.layout.simple_list_item_1);
  40.  
  41.         ListView lv = findViewById(R.id.lvFroitas_UD04_02_Menus);
  42.         lv.setAdapter(adaptador);
  43.  
  44.     }
  45.  
  46.     @Override
  47.     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
  48.         super.onCreateContextMenu(menu, v, menuInfo);
  49.         MenuInflater inflater = getMenuInflater();
  50.  
  51.         // Comprobamos se o menú contextual se lanzou sobre a etiqueta ou sobre
  52.         // a lista
  53.         if (v.getId() == R.id.tvTexto_UD04_02_Menus) {
  54.             inflater.inflate(R.menu.menu_ud04_02_context_etiqueta, menu);
  55.         }
  56.  
  57.         else if (v.getId() == R.id.lvFroitas_UD04_02_Menus) {
  58.             inflater.inflate(R.menu.menu_ud04_02_context_lista, menu);
  59.         }
  60.     }
  61.  
  62.     @Override
  63.     public boolean onContextItemSelected(MenuItem item) {
  64.         AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
  65.        
  66.         ListView lv = findViewById(R.id.lvFroitas_UD04_02_Menus);
  67.         ArrayAdapter<String> adaptador = (ArrayAdapter<String>) lv.getAdapter();
  68.  
  69.         switch (item.getItemId()) {
  70.  
  71.             // Ítems premidos sobre o TextView
  72.             // Lanza un Toast coa opción do menú contextual que se seleccinou
  73.             case R.id.mniItem1_04_02_context_etiq:
  74.                 Toast.makeText(this, "Menú contextual TextView:\n"+item.getTitle(), Toast.LENGTH_SHORT).show();
  75.                 return true;
  76.  
  77.             case R.id.mniItem2_04_02_context_etiq:
  78.                 Toast.makeText(this, "Menú contextual TextView:\n"+item.getTitle(), Toast.LENGTH_SHORT).show();
  79.                 return true;
  80.  
  81.             // Ítems premidos sobre o ListView
  82.             case R.id.mniItemBorrar_ud04_02_context_lista:
  83.                 adaptador.remove(adaptador.getItem(info.position));
  84.                 adaptador.setNotifyOnChange(true);
  85.                 return true;
  86.  
  87.             case R.id.mniItemDuplicar_ud04_02_context_lista:
  88.                 adaptador.add(adaptador.getItem(info.position));
  89.                 adaptador.setNotifyOnChange(true);
  90.  
  91.                 return true;
  92.             default:
  93.                 return super.onContextItemSelected(item);
  94.         }
  95.     }
  96.  
  97.     @Override
  98.     protected void onCreate(Bundle savedInstanceState) {
  99.         super.onCreate(savedInstanceState);
  100.         setContentView(R.layout.activity_ud04_02__menus);
  101.  
  102.         rexistarMenusEmerxentes();
  103.         engadirDatosLista();
  104.     }
  105.  
  106.  
  107. }
  • Liña 26: indicamos que TextView vai ter un menú contextual asociado.
  • Liña 29: indica que o ListView de froitas vai ter un menú contextual asociado.
  • Liñas 33,34: Creamos un Array estático que logo asignamos a un dinámico.
  • Liña 36: usamos o array dinámico para logo en tempo de execución poder engadir/borrar elementos do adaptador e por tanto do ListView.
Nota: Se poñemos un array como parámetro no ArrayAdapter, non poderíamos facer operacións de borrado e engadir novos elementos.


  • Liñas 46-60: onCreateContexMenu() vai ser chamado cando se prema durante un anaco sobre unha view, neste caso comprobamos sobre que view se premeu e lánzase ("inflase") o correspondente menú contextual, cada un deles definido nun ficheiro xml distinto.


  • Liñas 62-95: En función do id do ítem premido realizamos unhas accións ou outras como no caso dos menús básicos. Só que neste caso os ids proveñen de ítems de menús declarados en 2 ficheiros distintos.



Personalizar título do menú contextual

  • Se queremos que o menú contextual teña un título debemos usar o método: setHeaderTitle()
  • As seguintes imaxes amosan un exemplo para o caso do TextView e o ListView:


  • Os cambios a realizar no código Java son os seguintes:
  • No memento no que hai que crear o menú contextual:
  1.     @Override
  2.     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
  3.         super.onCreateContextMenu(menu, v, menuInfo);
  4.         MenuInflater inflater = getMenuInflater();
  5.  
  6.         // Comprobamos se o menú contextual se lanzou sobre a etiqueta ou sobre
  7.         // a lista
  8.         if (v.getId() == R.id.tvTexto_UD04_02_Menus) {
  9.             menu.setHeaderTitle("Etiqueta de texto");
  10.             inflater.inflate(R.menu.menu_ud04_02_context_etiqueta, menu);
  11.         }
  12.         else if (v.getId() == R.id.lvFroitas_UD04_02_Menus) {
  13.             AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
  14.  
  15.             ListView lv = findViewById(R.id.lvFroitas_UD04_02_Menus);
  16.             menu.setHeaderTitle(lv.getAdapter().getItem(info.position).toString());
  17.             inflater.inflate(R.menu.menu_ud04_02_context_lista, menu);
  18.         }
  19.     }
  • Liñas 9,16: establecemos o título para o menú contextual.





-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2015).