Diferencia entre revisiones de «Spinner a través de adaptador»
Ir a la navegación
Ir a la búsqueda
Línea 770: | Línea 770: | ||
<br /> | <br /> | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2018). | <br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2018). |
Revisión del 18:29 15 jun 2019
Sumario
Introdución
- Máis información en https://developer.android.com/reference/android/widget/Spinner
- Xa vimos na unidade 2 como crear un Spinner, pero o enlace dos datos co Spinner facíase a través dun atributo XML na definición do Spinner no Layout: android:entries.
- Agora imos facer o mesmo pero usando un adaptador.
- Colleremos os datos dende un array no código e logo dende un recurso XML.
- Se queremos cargar ditos recursos por programación:
- Deberemos facer uso dun obxecto da clase ArrayAdapter. Este obxecto serve coma ponte entre os datos e o spinner. A modificacións dos datos da lista sempre se fai no adaptador asociado á mesma e nunca sobre o spinner. Engadir, borrar, modificar, limpar,...todas esas operacións se teñen que facer sobre o adaptador.
- Deberemos de obter os datos para encher o spinner. Estes datos poden vir dun array gardado en /res/ e para referencialo teremos que facer uso do método getResources().
- Deberemos de establecer o aspecto (layout) que terá cada un dos 'views' que conforman cada elemento da lista (si, cada elemento da lista ten que ser un view :) )
- Deberemos establecer o aspecto (layout) de cada elemento do spinner cando prememos na lista e se despregan todos eles.
- Para crear un ArrayAdapter podemos seguir este código:
1 Spinner lista = findViewById(R.id.id_spinner);
2
3 ArrayAdapter<CharSequence>adaptador = ArrayAdapter.createFromResource(this,R.array.planetas_UD02_01_spinner,android.R.layout.simple_list_item_1);
4 adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
5 lista.setAdapter(adaptador);
- Na liña 3 creamos un ArrayAdapter facendo uso do método createFromResource. Dito método recibe como parámetros:
- O contexto
- Os datos do ArrayAdapter, que neste caso veñen dun recurso xa creado previamente noutro exercicio.
- O Layout que vai ter asociado cada view (elemento da lista, que dependendo do layout serán views como TextViews).
- Os layout que se poden empregar se poden consultar en http://wiki.cifprodolfoucha.es/index.php?title=Spinner#Caso_pr.C3.A1ctico
- O código fonte de cada layout se pode consultar en https://github.com/aosp-mirror/platform_frameworks_base/tree/master/core/res/res/layout
- Na liña 4, establecemos o layout que vai ter o spinner cando prememos sobre el e aparezan todos os elementos da lista. Podemos consultar o código fonte de dito layout.
- Na liña 5 asociamos o ArrayAdapter ao Spinner.
- Podemos facer o mesmo desta outra forma:
1 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,getResources().getStringArray(R.array.planetas_UD02_01_spinner));
- Para referenciar o array teríamos que facer uso da clase getResource() e obter o tipo correspondente (array).
- O ArrayAdapter está 'cheo' de métodos para engadir, borrar e modificar elementos da lista.
- Por exemplo:
- add(T object): Engade un elemento á lista de elementos.
- addAll(Collection<? extends T> collection): Engade unha colección.
- getCount(): Devolve o número de elementos da lista.
- getItem(int position): Devolve o elemento da lista en base a súa posición (empeza en 0)
- insert(T object, int index) : Engade un elemento na posición indicada.
- remove(T object): Elimina un elemento da lista.
- clear(): Borra todos os elementos da lista.
- Importante: Calquera modificación que se faga sobre os elementos da lista facendo uso do adaptador, leva consigo a 'obriga' de informar ao view dos cambios para que os reflicta.
- Isto se consigo chamando a un destes dous métodos:
- Método setNotifyOnChange(boolean notifyOnChange), cun valor true no parámetro.
- Método notifyDataSetChanged.
- O segundo normalmente se chama cando hai algún cambio estrutural na lista (remove, add,...). En teoría chamarano o primeiro método automaticamente pero algunhas veces non funciona e é necesario chamalo explicitamente. Se debe chamar a un dos dous, non os dous.
- Por exemplo, o código anterior se podería cambiar por:
1 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item); 2 adapter.addAll(getResources().getStringArray(R.array.planetas_UD02_01_spinner)); 3 adapter.setNotifyOnChange(true);
- A xestión de eventos neste control inclúe a interface que controla cando un elemento da lista é premido. É a interface OnItemSelectedListener e se rexistra có método setOnItemSelectedListener(AdapterView.OnItemClickListener l) do Spinner.
- Ao facelo, deberá implementarse estes dous método:
1 @Override 2 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 3 4 } 5 6 @Override 7 public void onNothingSelected(AdapterView<?> parent) { 8 9 }
- O segundo método se chama cando non se selecciona ningún elemento e desaparece a lista.
- O primeiro cando se selecciona un elemento da lista.
- Leva como parámetros:
- O adaptador asociado á lista.
- O view que foi seleccionado (lembrar que cando se crea o adaptador se establece un layout para cada compoñente da lista)
- A posición do elemento seleccionado na lista (empeza en 0)
- Un identificador para a fila que foi seleccionada.
Caso práctico 1
- Partimos que xa temos creado o proxecto inicial como xa indicamos anteriormente.
- Se non o temos creado antes, crearemos un novo paquete de nome: Adaptadores como un subpaquete do teu paquete principal.
- Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_01_Spinners 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.
- Cada ítem do Spinner é tratado como unha View, neste caso de tipo TextView.
O XML do layout
- Observar como a vista Spinner non ten a entrada android:entries.
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=".Adaptadores.UD04_01_Spinners">
8
9 <Spinner
10 android:id="@+id/spnLista_UD02_02_spinner"
11 android:layout_width="0dp"
12 android:layout_height="wrap_content"
13 android:layout_marginEnd="8dp"
14 android:layout_marginStart="8dp"
15 android:layout_marginTop="8dp"
16 android:dropDownWidth="match_parent"
17 app:layout_constraintEnd_toEndOf="parent"
18 app:layout_constraintStart_toStartOf="parent"
19 app:layout_constraintTop_toTopOf="parent" />
20 </android.support.constraint.ConstraintLayout>
- Partimos do exercicio de spinner feito anteriormente, no que está definido un array de datos, nun arquivo de /res/values:
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3
4 <string-array name="planetas_UD02_01_spinner">
5 <item>Mercurio</item>
6 <item>Venus</item>
7 <item>Terra</item>
8 <item>Marte</item>
9 <item>Xúpiter</item>
10 <item>Saturno</item>
11 <item>Urano</item>
12 <item>Neptuno</item>
13 </string-array>
14
15 </resources>
- O código da Activity:
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.View;
6 import android.widget.AdapterView;
7 import android.widget.ArrayAdapter;
8 import android.widget.Spinner;
9 import android.widget.TextView;
10 import android.widget.Toast;
11
12 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
13
14 public class UD04_01_Spinners extends Activity {
15
16 private void cargarLista() {
17
18 Spinner lista = findViewById(R.id.spnLista_UD02_02_spinner);
19
20 ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
21 adapter.addAll(getResources().getStringArray(R.array.planetas_UD02_01_spinner));
22 lista.setAdapter(adapter);
23
24 lista.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
25 @Override
26 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
27 //String datoLista = (String)parent.getItemAtPosition(position); // Poderíamos obter o dato desta forma (fixarse no Cast)
28 String datoLista = ((TextView) view).getText().toString(); // ou desta outra forma
29 Toast.makeText(getApplicationContext(),"Elemento seleccionado:" + datoLista + " na posición "+ String.valueOf(position),Toast.LENGTH_LONG).show();
30 }
31
32 @Override
33 public void onNothingSelected(AdapterView<?> parent) {
34
35 }
36 });
37
38 }
39 @Override
40 protected void onCreate(Bundle savedInstanceState) {
41 super.onCreate(savedInstanceState);
42 setContentView(R.layout.activity_ud04_01__spinners);
43
44 cargarLista();
45
46 }
47 }
- Liñas 20-22: Usamos unha das formas vistas para crear o adaptador e asocialo ao spinner.
- Liña 24: Rexistramos a interface que xestiona o evento de selección dun elemento da lista.
- Liñas 26-30: Facemos uso do método onItemSelected() e os seus parámetros para obter o dato da lista seleccionado.
Caso práctico 2: Usando un array estático en Java
- Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_02_Spinners 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 cargaremos a fonte de datos dun array local.
O código XML da activity é:
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=".Adaptadores.UD04_02_Spinners">
8
9 <Spinner
10 android:id="@+id/spnLista_UD04_02_Spinner"
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 app:layout_constraintBottom_toBottomOf="parent"
18 app:layout_constraintEnd_toEndOf="parent"
19 app:layout_constraintStart_toStartOf="parent"
20 app:layout_constraintTop_toTopOf="parent" />
21 </android.support.constraint.ConstraintLayout>
- Ao final do código explícase como se enlaza a fonte de datos co adaptador e este co spinner.
- Observar as liñas marcadas.
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.View;
6 import android.widget.AdapterView;
7 import android.widget.ArrayAdapter;
8 import android.widget.Spinner;
9 import android.widget.TextView;
10 import android.widget.Toast;
11
12 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
13
14 public class UD04_02_Spinners extends Activity {
15
16 private void cargarLista(){
17
18 Spinner spinFroitas = (Spinner) findViewById(R.id.spnLista_UD04_02_Spinner);
19
20 // Fonte de datos
21 String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };
22
23 // Enlace do adaptador cos datos
24 ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, froitas);
25
26 // Opcional: layout usuado para representar os datos no Spinner
27 adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
28
29 // Enlace do adaptador co Spinner do Layout.
30 spinFroitas.setAdapter(adaptador);
31
32 // Escoitador
33 spinFroitas.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
34 @Override
35 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
36 //Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();
37 Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();
38
39 }
40
41 @Override
42 public void onNothingSelected(AdapterView<?> arg0) {
43 // TODO Auto-generated method stub
44 }
45 }); // Fin da clase anónima
46
47 }
48
49
50 @Override
51 protected void onCreate(Bundle savedInstanceState) {
52 super.onCreate(savedInstanceState);
53 setContentView(R.layout.activity_ud04_02__spinners);
54
55 cargarLista();
56 }
57 }
- Liña 23: Definimos a fonte de datos, neste caso un array estático.
- Liña 26: Definimos o adaptador de tipo ArrayAdapter. Pasámoslle como parámetros:
- Contexto,
- O int, identificador de recurso de layout que se vai usar para representar a Vista de Selección, neste caso usamos un predefinido. O usuario pode experimentar con outros tipos (android.R.layout.... CTRL+ESPAZO) e ver que outras formas hai de presentar os datos nun Spinner.
- Un array de obxectos, neste caso de Strings.
- Para ver outros construtores e métodos: http://developer.android.com/reference/android/widget/ArrayAdapter.html
- Liña 29: setDropDownViewResource(int), indica como se vai representar cada un dos ítems do Spinner. Usamos un layout xa predefinido. O usuario pode experimentar usando outros distintos, predefinidos ou propios.
- Liña 32: establece o adaptador que subministra os datos ao Spinner.
- Liña 35: O escoitador é o mesmo que cando non se usaba un adaptador.
- Liñas 38,39: As dúas liñas fan o mesmo, pero no segundo caso observar como recollemos a vista (view) que nos devolve o evento ao premer nun ítem do Spinner. Esa view é do tipo TextView e por iso facemos un cast e logo xa lle podemos aplicar métodos da clase TextView, como getText().
Caso práctico 3: Uso dun array dinámico
- Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_03_Spinners 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 cargaremos a fonte de datos dun array ArrayList. Cando vexamos o acceso a base de datos, os datos virán dunha táboa.
O código XML da activity é:
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=".Adaptadores.UD04_02_Spinners">
8
9 <Spinner
10 android:id="@+id/spnLista_UD04_03_Spinner"
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 app:layout_constraintBottom_toBottomOf="parent"
18 app:layout_constraintEnd_toEndOf="parent"
19 app:layout_constraintStart_toStartOf="parent"
20 app:layout_constraintTop_toTopOf="parent" />
21 </android.support.constraint.ConstraintLayout>
- Nos dous casos anteriores o contido do Spinner é estático e defínese en tempo de compilación, non de execución.
- Se usamos arrays dinámicos podemos crear a fonte de datos en tempo de execución antes de pasarlla ao adaptador.
- Así imos poder usar datos de ficheiros, bases de datos, etc e crear unha fonte de datos para un Spinner en tempo de execución.
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.view.View;
6 import android.widget.AdapterView;
7 import android.widget.ArrayAdapter;
8 import android.widget.Spinner;
9 import android.widget.TextView;
10 import android.widget.Toast;
11
12 import java.util.ArrayList;
13
14 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
15
16 public class UD04_03_Spinners extends Activity {
17
18 private void cargarLista(){
19
20 Spinner spinFroitas = (Spinner) findViewById(R.id.spnLista_UD04_03_Spinner);
21
22 ArrayList<String> animais = new ArrayList<String>();
23
24 animais.add("CABALLOS");
25 animais.add("GATITOS");
26 animais.add("PERROS");
27 animais.add("RATONES");
28
29 // Enlace do adaptador cos datos
30 ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, animais);
31
32 // Enlace do adaptador co Spinner do Layout.
33 spinFroitas.setAdapter(adaptador);
34
35 // Escoitador
36 spinFroitas.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
37 @Override
38 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
39 //Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();
40 Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();
41
42 }
43
44 @Override
45 public void onNothingSelected(AdapterView<?> arg0) {
46 // TODO Auto-generated method stub
47 }
48 }); // Fin da clase anónima
49
50 }
51
52
53 @Override
54 protected void onCreate(Bundle savedInstanceState) {
55 super.onCreate(savedInstanceState);
56 setContentView(R.layout.activity_ud04_03__spinners);
57
58 cargarLista();
59 }
60 }
- Liñas 23-28: Neste caso os elementos do array engádense en tempo de execución ao array animais, que neste caso e do tipo ArrayList.
- O resto é exactamente igual.
Caso práctico 4: Personalizando o deseño
- Dentro do paquete Adaptadores crear unha nova 'Empty Activity' de nome: UD04_04_Spinners 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.
- Como indicamos dende o inicio, cando creamos o Spinner tamén creamos un adaptador sobre o cal indicamos o layout de cada compoñente da lista.
- Podemos crear nos mesmos o deseño que queiramos cos datos que queiramos que aparezan na lista.
- Para facer o anterior, temos que crear o noso propio adaptador.
- Nesta práctica creamos un layout formado por unha imaxe e un texto para cada elemento da lista do spinner.
- Como o que queremos é facer un deseño específico para cada 'fila' de elementos da lista / spinner, imos crear o Layout que vai representar cada fila:
Nome Arquivo do layout: spinner_ud04_04.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:app="http://schemas.android.com/apk/res-auto"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent">
6
7 <ImageView
8 android:id="@+id/imgVImaxen_UD04_04_Spinners"
9 android:layout_width="wrap_content"
10 android:layout_height="wrap_content"
11 android:layout_weight="1"
12 />
13
14 <TextView
15 android:id="@+id/txtTexto_UD04_04_Spinners"
16 android:layout_width="wrap_content"
17 android:layout_height="wrap_content"
18 android:layout_weight="2"
19 android:text="TextView" />
20 </LinearLayout>
- Como vemos, estamos a definir un layout cun Imageview e un TextView. Pero poderíamos poñer calquera lauyout con calquera número de elementos e deseño.
- Partimos dun exercicio anterior onte xa tiñamos definidos nun array os datos do exercicio:
1 <?xml version="1.0" encoding="utf-8"?>
2 <resources>
3
4 <string-array name="planetas_UD02_01_spinner">
5 <item>Mercurio</item>
6 <item>Venus</item>
7 <item>Terra</item>
8 <item>Marte</item>
9 <item>Xúpiter</item>
10 <item>Saturno</item>
11 <item>Urano</item>
12 <item>Neptuno</item>
13 </string-array>
14
15 </resources>
- Agora crearemos o Adaptador.
- Despois de facer o anterior teremos un código coma isto:
- Arquivo: Adaptador_UD04_04_Spinners
1 public class Adaptador_UD04_04_Spinners extends ArrayAdapter {
2
3 public AdaptadorPrueba(@NonNull Context context, int resource) {
4 super(context, resource);
5 }
6 }
- Agora debemos ter claro que o que imos a 'enviar' a este adaptador van ser os datos necesarios para que 'constrúa' a lista de elementos.
- No noso caso, queremos que faga unha lista de elementos no que cada elemento vai ser un texto (TextView) e unha imaxe (ImageView).
- Polo tanto teremos que enviar un array de cadeas (para o texto) e algo para facer unha imaxe. No exemplo imos a enviarlle imaxes gardadas en /res/drawable/ e polo tanto serán un array de enteiros (lembrar que en /res/ todo se referencia por números facendo uso da clase R). Poderíamos enviar URL e que o ImageView cargase a imaxe de dita URL.
- Modificamos o construtor para que recolla estes datos. Como teremos que facer uso deles noutros métodos, crearemos propiedades locais na clase:
1 public class Adaptador_UD04_04_Spinners extends ArrayAdapter {
2
3 int[] imaxes; // Lista de imaxes a cargar. Lembra que en res todo son números Se foran url poderíamos cambialo por String[]
4 String[] textos;
5 Context mContext;
6
7 public Adaptador_UD04_04_Spinners(@NonNull Context context, int[]imaxes,String[]textos) {
8 super(context, R.layout.spinner_ud04_04); // Enviamos o layout que imos utilizar
9
10 this.imaxes = imaxes;
11 this.textos = textos;
12 this.mContext = context;
13 }
14
15 }
- Fixarse na liña 8, que enviamos ao construtor da clase ArrayAdapter o layout que vai 'gardar' cada elemento da lista no spinner.
- Agora, para que funcione o adaptador temos que sobreescribir a lo menos tres métodos:
- int getCount(): Devolve o número de elementos da lista. Fixarse que no noso caso, o número de elementos da lista o sabemos por calquera dos dous arrays onde gardamos os datos. Se creamos catro elementos, a propiedade textos.length será catro.
- View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent): Este método ten que devolver o view de cada elemento da fila. Fixarse que este 'view' no noso caso será un LinearLayout formado por dos Views (un TextView e un ImageView). E o view que visualiza o elemento escollida da lista.
- View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent): Devolve o view que conforma cada elemento da lista cando prememos sobre a mesma (a lista despregable). Pero aquí amosamos o view de cada elemento da lista despregable.
- Fixarse que no caso dos métodos que devolven un view, podemos facer nos un dinamicamente e devolvelo.
- Por exemplo, se fago isto:
1 @Override
2 public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
3 TextView proba = new TextView(mContext);
4 proba.setText("OOOOOOOO");
5 return proba;
6 }
- Aparece isto:
- Isto sería útil se queremos que cando escollamos un elemento apareza unha información e cando estea escollido apareza outra. Máis información neste enlace.
- No noso caso queremos que visualmente apareza o mesmo cando temos un elemento escollido da lista, como cando aparece o despregable da mesma.
- Como o view que representa o elemento seleccionado da lista o obtemos do método getView (como comentamos antes) o código quedaría así:
1 @Override
2 public int getCount() {
3 return textos.length; // Poderíamos poñer tamén o número de imaxes.
4 }
5
6 @Override
7 public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
8 return getView(position,convertView,parent);
9 }
10
11 @NonNull
12 @Override
13 public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
14 return super.getView(position, convertView, parent);
15 }
- Liña 3: Devolvemos o número de textos enviados como parámetro do constructor.
- Liña 8: Devolvemos o view do método getView que imos a modificar.
- Agora ven o máis importante, que é crear o view que conforma o elemento seleccionado no Spinner:
- O proceso para facelo é o seguinte:
- Fixámonos na definición do método getView: public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
- Ese obxecto da clase View vai 'levar' o layout que temos definido para cada elemento da fila.
- E os datos cos que vai encher dito layout van ir no método setTag xa comentado nesta wiki.
- O primeiro é cargar o layout no 'convertView'.
- Para iso temos que pasar o layout dun arquivo XML a un obxecto que poida ser empregado en programación.
- Iso se fai facendo un 'inflate':
1 LayoutInflater mInflater = (LayoutInflater) mContext. 2 getSystemService(Context.LAYOUT_INFLATER_SERVICE); 3 convertView = mInflater.inflate(R.layout.spinner_ud04_04, parent, false);
- Xa analicaremos en detalle este código. Por agora quedade coa idea de que estas liñas fan que o LinearLayout co botón e a imaxe pasa a ser un obxecto que se garda en convertView.
- Segundo, debemos de pasar os datos de cada elemento por medio do método setTag.
- Non perdades a idea de que a este método se chama 'por cada elemento da lista', sendo o parámetro 'position' o que nos di a posición do elemento que se vai amosar.
- Para facer isto, crearemos una clase na que gardaremos os views que se van pasar ao layout. Os views son un ImageView e un TextView:
1 private static class ViewHolder { 2 ImageView mImaxe; 3 TextView mTexto; 4 }
- Agora creamos un obxecto de dita clase e indicamos a que se corresponde cada un dese views no arquivo de Layout. Ademáis gardamos dita información no convertView, na propiedade Tag:
1 Adaptador_UD04_04_Spinners.ViewHolder viewFila = new Adaptador_UD04_04_Spinners.ViewHolder(); 2 3 viewFila.mImaxe = (ImageView) convertView.findViewById(R.id.imgVImaxen_UD04_04_Spinners); 4 viewFila.mTexto = (TextView) convertView.findViewById(R.id.txtTexto_UD04_04_Spinners); 5 convertView.setTag(viewFila);
- Terceiro, asociamos os datos concretos de cada elemento aos datos de cada view e devolvemos o 'convertView':
1 viewFila.mImaxe.setImageResource(imaxes[position]); 2 viewFila.mTexto.setText(textos[position]); 3 4 return convertView;
- Cuarto, como a este método se pode chamar varias veces (é dicir, despregar a lista), a segunda ou sucesivas veces que se chame, os datos xa non cambian, polo que non é necesario volver a crear o 'converView' que xa virá con datos, incluído o tag, polo que podemos recuperar ditos datos có método getTag.
- Agora se entende por que é necesario chamar ao método setNotifyOnChange(boolean notifyOnChange) ?
- O código completo:
Arquivo: Adaptador_UD04_04_Spinners
1 public class Adaptador_UD04_04_Spinners extends ArrayAdapter { 2 3 int[] imaxes; // Lista de imaxes a cargar. Lembra que en res todo son números Se foran url poderíamos cambialo por String[] 4 String[] textos; 5 Context mContext; 6 7 public Adaptador_UD04_04_Spinners(@NonNull Context context, int[]imaxes,String[]textos) { 8 super(context, R.layout.spinner_ud04_04); // Enviamos o layout que imos utilizar 9 10 this.imaxes = imaxes; 11 this.textos = textos; 12 this.mContext = context; 13 } 14 15 @Override 16 public int getCount() { 17 //return super.getCount(); 18 return textos.length; // Poderíamos poñer tamén o número de imaxes. 19 } 20 21 @Override 22 public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 23 return getView(position,convertView,parent); 24 } 25 26 private static class ViewHolder { 27 ImageView mImaxe; 28 TextView mTexto; 29 } 30 @NonNull 31 @Override 32 public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { 33 //return super.getView(position, convertView, parent); 34 35 Adaptador_UD04_04_Spinners.ViewHolder viewFila = new Adaptador_UD04_04_Spinners.ViewHolder(); 36 if (convertView == null) { 37 LayoutInflater mInflater = (LayoutInflater) mContext. 38 getSystemService(Context.LAYOUT_INFLATER_SERVICE); 39 convertView = mInflater.inflate(R.layout.spinner_ud04_04, parent, false); 40 viewFila.mImaxe = (ImageView) convertView.findViewById(R.id.imgVImaxen_UD04_04_Spinners); 41 viewFila.mTexto = (TextView) convertView.findViewById(R.id.txtTexto_UD04_04_Spinners); 42 convertView.setTag(viewFila); 43 } else { 44 viewFila = (Adaptador_UD04_04_Spinners.ViewHolder) convertView.getTag(); 45 } 46 viewFila.mImaxe.setImageResource(imaxes[position]); 47 viewFila.mTexto.setText(textos[position]); 48 49 return convertView; 50 } 51 52 }
- Unha vez que temos o adaptador creado teremos que ir á activity e asociar o spinner a dito adaptador.
- Como non temos moitas imaxes en /res/ imos asociar a mesma imaxe a todos os elementos da lista. Partimos que temos unha imaxe en res de nome: R.drawable.ok (se non é o caso poñede outra calquera).
Arquivo: UD04_04_Spinners
1 package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.widget.Spinner;
6
7 import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
8
9 public class UD04_04_Spinners extends Activity {
10
11 private void cargarLista(){
12 String datos[] = getResources().getStringArray(R.array.planetas_UD02_01_spinner);
13 int[] imaxes = new int[datos.length];
14 for(int cont=0;cont<datos.length;cont++){
15 imaxes[cont]=R.drawable.ok;
16 }
17
18 Spinner lista = findViewById(R.id.spnLista_UD04_04_Spinners);
19
20 Adaptador_UD04_04_Spinners meuAdaptador = new Adaptador_UD04_04_Spinners(this,imaxes,datos);
21 lista.setAdapter(meuAdaptador);
22
23 }
24
25 @Override
26 protected void onCreate(Bundle savedInstanceState) {
27 super.onCreate(savedInstanceState);
28 setContentView(R.layout.activity_ud04_04__spinners);
29
30 cargarLista();
31 }
32 }
-- Ángel D. Fernández González e Carlos Carrión Álvarez -- (2018).