Menús

De MediaWiki
Ir a la navegación Ir a la búsqueda

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).