Diferencia entre revisiones de «Menús»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 158: Línea 158:
 
</menu>
 
</menu>
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
'''IMPORTANTE:''' Se estades a empregar unha AppCompactActivity asegurádevos de que estea definido o espazo de nomes app no arquivo xml, da forma: xmlns:app="http://schemas.android.com/apk/res-auto"
  
  

Revisión del 08:55 23 oct 2019

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

  • Imos ver como personalizar a ActionBar (chámase ToolBar e forma parte da AppBar, a partires da versión API 21) e que aparezan opcións de menú:
PDM Biblioteca compat 1.jpg
Imaxe obtida desta web



  • Nota:
  • 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 opcións de menú (un deles con submenús e outro cunha icona na Barra de Acción).
  • Se queremos que a ActionBar (ToolBar dentro da 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



Empregando AppCompactActivity

  • Se estades a desenvolver un proxecto e as vosos activities derivan de dita clase para ter compatibilidade con versións de Android anteriores, podemos facer que a AppBar apareza de dúas formas:
  • Empregando un theme (estilo) que incorpore a AppBar.
  • Empregando un theme que non incorpore' o AppBar e engadindo ao Layout da Activity o View que vai representar a AppBar.
  • A opción recomendada é a segunda, xa que temos un control completo sobre o aspecto e posición da AppBar.




O código que hai que engadir na activity no método 'onCreate' é:
1         Toolbar myToolbar = findViewById(R.id.toolbar_UD04_01_Menus);
2         setSupportActionBar(myToolbar);
Nota: Indicar que myToolbar representa a ToolBar e podemos aplicarlle diferentes métodos coma hide() para ocultala.



  • A nivel do asistente de Android Studio podemos crear unha AppBar (que inclúe ToolBar) con efectos coma facerse invisible automaticamente cando hai un scroll, poñer imaxes de fondo,...o único que tedes que facer é arrastrar o compoñentes AppBarLayout en vez do ToolBar de antes.




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>

IMPORTANTE: Se estades a empregar unha AppCompactActivity asegurádevos de que estea definido o espazo de nomes app no arquivo xml, da forma: xmlns:app="http://schemas.android.com/apk/res-auto"


  • Agora comentaremos algúns dos atributos que podemos cambiar.
Lembrar que o podemos facer graficamente ou directamente no editor na vista XML.
  • Atributo android:icon: Icona asociada a esta opción de menú. Lembrade que xa vimos anteriormente como facer uso do Image Asset Store. Agora deberemos escoller a categoría 'Action bar and Tab Icons'.
  • 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: activity_ud04_01__menus

(Nota: Neste exemplo estamos a empregar un theme que xa amosa a ToolBar. No voso caso pode aparecer ademais o View ToolBar)

 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/...): mnu_ud04_01_menus.xml
 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_mniItem3_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.mnu_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 
65 
66 }
  • 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 aplicado a un RecyclerView


Menú contextual: Caso Práctico aplicado a unha ListView e un TextView

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'. 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 (deberedes de aplicalo ao voso caso).


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