Diferencia entre revisiones de «Spinner a través de adaptador»

De MediaWiki
Ir a la navegación Ir a la búsqueda
 
(No se muestran 3 ediciones intermedias de 2 usuarios)
Línea 1: Línea 1:
−
==Introdución==
+
* [https://wiki.cifprodolfoucha.es/index.php?title=Spinner_con_Adaptadores Información movida a este enlace]
−
 
 
−
* Máis información en [https://developer.android.com/reference/android/widget/Spinner https://developer.android.com/reference/android/widget/Spinner]
 
−
 
 
−
<br />
 
−
*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 [https://developer.android.com/reference/android/widget/ArrayAdapter?hl=es-419 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 [https://developer.android.com/reference/android/content/Context?hl=es-419#getResources() 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:
 
−
<syntaxhighlight lang="java" enclose="div" line highlight="">
 
−
        Spinner lista = findViewById(R.id.id_spinner);
 
−
 
 
−
        ArrayAdapter<CharSequence>adaptador = ArrayAdapter.createFromResource(this,R.array.planetas_UD02_01_spinner,android.R.layout.simple_list_item_1);
 
−
        adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
−
        lista.setAdapter(adaptador);
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
:* Na liña 3 creamos un ArrayAdapter facendo uso do [https://developer.android.com/reference/android/widget/ArrayAdapter?hl=es-419#createFromResource(android.content.Context,%20int,%20int) 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 [http://wiki.cifprodolfoucha.es/index.php?title=Spinner#Caso_pr.C3.A1ctico 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 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 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 [https://github.com/aosp-mirror/platform_frameworks_base/tree/master/core/res/res/layout o código fonte de dito layout].
 
−
 
 
−
:* Na liña 5 asociamos o ArrayAdapter ao Spinner.
 
−
 
 
−
 
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
* Podemos facer o mesmo desta outra forma:
 
−
:<syntaxhighlight lang="java" line enclose="div" highlight="">
 
−
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item,getResources().getStringArray(R.array.planetas_UD02_01_spinner));
 
−
</syntaxhighlight>
 
−
 
 
−
: 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:
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#add(T) add(T object)]: Engade un elemento á lista de elementos.
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#addAll(java.util.Collection%3C?%20extends%20T%3E) addAll(Collection<? extends T> collection)]: Engade unha colección.
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#getCount() getCount()]: Devolve o número de elementos da lista.
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#getItem(int) getItem(int position)]: Devolve o elemento da lista en base a súa posición (empeza en 0)
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#insert(T,%20int) insert(T object, int index) ]: Engade un elemento na posición indicada.
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#remove(T) remove(T object)]: Elimina un elemento da lista.
 
−
:* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#clear() clear()]: Borra todos os elementos da lista.
 
−
 
 
−
* '''<u>Importante:</u>'''
 
−
:* 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:
 
−
::* [https://developer.android.com/reference/android/widget/ArrayAdapter.html#setNotifyOnChange(boolean) Método setNotifyOnChange(boolean notifyOnChange)], cun valor true no parámetro.
 
−
::* [https://developer.android.com/reference/android/widget/BaseAdapter.html#notifyDataSetChanged() 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:
 
−
:<syntaxhighlight lang="java" enclose="div" line highlight="">
 
−
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_spinner_item);
 
−
adapter.addAll(getResources().getStringArray(R.array.planetas_UD02_01_spinner));
 
−
adapter.setNotifyOnChange(true);
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
* A xestión de eventos neste control inclúe a interface que controla cando un elemento da lista é premido. É a [https://developer.android.com/reference/android/widget/AdapterView.OnItemSelectedListener interface OnItemSelectedListener] e se rexistra có [https://developer.android.com/reference/android/widget/AdapterView.html#setOnItemSelectedListener(android.widget.AdapterView.OnItemSelectedListener) método setOnItemSelectedListener(AdapterView.OnItemClickListener l)] do Spinner.
 
−
: Ao facelo, deberá implementarse estes dous método:
 
−
:<syntaxhighlight lang="java" enclose="div" line highlight="">
 
−
            @Override
 
−
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
 
−
 
 
−
            }
 
−
 
 
−
            @Override
 
−
            public void onNothingSelected(AdapterView<?> parent) {
 
−
 
 
−
            }
 
−
 
 
−
</syntaxhighlight>
 
−
 
 
−
:: 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 [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa indicamos anteriormente].
 
−
: Se non o temos creado antes, crearemos un novo paquete de nome: '''Adaptadores''' como un subpaquete do teu paquete principal.
 
−
 
 
−
 
 
−
<br />
 
−
* 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 [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base].
 
−
 
 
−
 
−
<br />
 
−
 
 
−
 
 
−
<gallery caption="Spinner cun Adapter" widths="350" heights="300px" perrow="2">
 
−
Image:PDM_adaptador_2.jpg
 
−
Image:PDM_adaptador_2.jpg
 
−
</gallery>
 
−
 
 
−
*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'''.
 
−
 
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="" >
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 
−
    xmlns:app="http://schemas.android.com/apk/res-auto"
 
−
    xmlns:tools="http://schemas.android.com/tools"
 
−
    android:layout_width="match_parent"
 
−
    android:layout_height="match_parent"
 
−
    tools:context=".Adaptadores.UD04_01_Spinners">
 
−
 
 
−
    <Spinner
 
−
        android:id="@+id/spnLista_UD02_02_spinner"
 
−
        android:layout_width="0dp"
 
−
        android:layout_height="wrap_content"
 
−
        android:layout_marginEnd="8dp"
 
−
        android:layout_marginStart="8dp"
 
−
        android:layout_marginTop="8dp"
 
−
        android:dropDownWidth="match_parent"
 
−
        app:layout_constraintEnd_toEndOf="parent"
 
−
        app:layout_constraintStart_toStartOf="parent"
 
−
        app:layout_constraintTop_toTopOf="parent" />
 
−
</android.support.constraint.ConstraintLayout>
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
* Partimos do exercicio de spinner feito anteriormente, no que está definido un array de datos, nun arquivo de /res/values:
 
−
<syntaxhighlight lang="xml" line enclose="div" highlight="" >
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<resources>
 
−
 
 
−
    <string-array name="planetas_UD02_01_spinner">
 
−
        <item>Mercurio</item>
 
−
        <item>Venus</item>
 
−
        <item>Terra</item>
 
−
        <item>Marte</item>
 
−
        <item>Xúpiter</item>
 
−
        <item>Saturno</item>
 
−
        <item>Urano</item>
 
−
        <item>Neptuno</item>
 
−
    </string-array>
 
−
 
 
−
</resources>
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
 
 
−
* O código da Activity:
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="20-22,24-30,44" >
 
−
package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 
−
 
 
−
import android.app.Activity;
 
−
import android.os.Bundle;
 
−
import android.view.View;
 
−
import android.widget.AdapterView;
 
−
import android.widget.ArrayAdapter;
 
−
import android.widget.Spinner;
 
−
import android.widget.TextView;
 
−
import android.widget.Toast;
 
−
 
 
−
import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 
−
 
 
−
public class UD04_01_Spinners extends Activity {
 
−
 
 
−
    private void cargarLista() {
 
−
 
 
−
        Spinner lista = findViewById(R.id.spnLista_UD02_02_spinner);
 
−
 
 
−
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
 
−
        adapter.addAll(getResources().getStringArray(R.array.planetas_UD02_01_spinner));
 
−
        lista.setAdapter(adapter);
 
−
 
 
−
        lista.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
 
−
            @Override
 
−
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
 
−
                //String datoLista = (String)parent.getItemAtPosition(position);    // Poderíamos obter o dato desta forma (fixarse no Cast)
 
−
                String datoLista = ((TextView) view).getText().toString();          // ou desta outra forma
 
−
                Toast.makeText(getApplicationContext(),"Elemento seleccionado:" + datoLista + " na posición "+ String.valueOf(position),Toast.LENGTH_LONG).show();
 
−
            }
 
−
 
 
−
            @Override
 
−
            public void onNothingSelected(AdapterView<?> parent) {
 
−
 
 
−
            }
 
−
        });
 
−
 
 
−
    }
 
−
    @Override
 
−
    protected void onCreate(Bundle savedInstanceState) {
 
−
        super.onCreate(savedInstanceState);
 
−
        setContentView(R.layout.activity_ud04_01__spinners);
 
−
 
 
−
        cargarLista();
 
−
 
 
−
    }
 
−
}
 
−
</syntaxhighlight>
 
−
 
 
−
:* 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 [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base].
 
−
 
 
−
 
−
<br />
 
−
 
 
−
* Neste caso cargaremos a fonte de datos dun array local.
 
−
[[Imagen:PDM_adaptador_3.jpg|400px|center]]
 
−
 
 
−
 
 
−
<br />
 
−
O código XML da activity é:
 
−
<syntaxhighlight lang="xml" line enclose="div" highlight="">
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 
−
    xmlns:app="http://schemas.android.com/apk/res-auto"
 
−
    xmlns:tools="http://schemas.android.com/tools"
 
−
    android:layout_width="match_parent"
 
−
    android:layout_height="match_parent"
 
−
    tools:context=".Adaptadores.UD04_02_Spinners">
 
−
 
 
−
    <Spinner
 
−
        android:id="@+id/spnLista_UD04_02_Spinner"
 
−
        android:layout_width="wrap_content"
 
−
        android:layout_height="wrap_content"
 
−
        android:layout_marginBottom="8dp"
 
−
        android:layout_marginEnd="8dp"
 
−
        android:layout_marginStart="8dp"
 
−
        android:layout_marginTop="8dp"
 
−
        app:layout_constraintBottom_toBottomOf="parent"
 
−
        app:layout_constraintEnd_toEndOf="parent"
 
−
        app:layout_constraintStart_toStartOf="parent"
 
−
        app:layout_constraintTop_toTopOf="parent" />
 
−
</android.support.constraint.ConstraintLayout>
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
<br />
 
−
*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.
 
−
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="23,26,29,32,35,36,37" >
 
−
package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 
−
 
 
−
import android.app.Activity;
 
−
import android.os.Bundle;
 
−
import android.view.View;
 
−
import android.widget.AdapterView;
 
−
import android.widget.ArrayAdapter;
 
−
import android.widget.Spinner;
 
−
import android.widget.TextView;
 
−
import android.widget.Toast;
 
−
 
 
−
import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 
−
 
 
−
public class UD04_02_Spinners extends Activity {
 
−
 
 
−
    private void cargarLista(){
 
−
 
 
−
            Spinner spinFroitas = (Spinner) findViewById(R.id.spnLista_UD04_02_Spinner);
 
−
 
 
−
            // Fonte de datos
 
−
            String[] froitas = new String[] { "Pera", "Mazá", "Plátano" };
 
−
 
 
−
            // Enlace do adaptador cos datos
 
−
            ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, froitas);
 
−
 
 
−
            // Opcional: layout usuado para representar os datos no Spinner
 
−
            adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
 
−
 
 
−
            // Enlace do adaptador co Spinner do Layout.
 
−
            spinFroitas.setAdapter(adaptador);
 
−
 
 
−
            // Escoitador
 
−
            spinFroitas.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
 
−
                @Override
 
−
                public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
 
−
                    //Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();
 
−
                    Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();
 
−
 
 
−
                }
 
−
 
 
−
                @Override
 
−
                public void onNothingSelected(AdapterView<?> arg0) {
 
−
                    // TODO Auto-generated method stub
 
−
                }
 
−
            }); // Fin da clase anónima
 
−
 
 
−
    }
 
−
 
 
−
 
 
−
    @Override
 
−
    protected void onCreate(Bundle savedInstanceState) {
 
−
        super.onCreate(savedInstanceState);
 
−
        setContentView(R.layout.activity_ud04_02__spinners);
 
−
 
 
−
        cargarLista();
 
−
    }
 
−
}
 
−
</syntaxhighlight>
 
−
*'''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 [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base].
 
−
 
 
−
 
−
<br />
 
−
 
 
−
* 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.
 
−
[[Imagen:PDM_adaptador_4.jpg|400px|center]]
 
−
 
 
−
 
 
−
<br />
 
−
O código XML da activity é:
 
−
<syntaxhighlight lang="xml" line enclose="div" highlight="">
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
 
−
    xmlns:app="http://schemas.android.com/apk/res-auto"
 
−
    xmlns:tools="http://schemas.android.com/tools"
 
−
    android:layout_width="match_parent"
 
−
    android:layout_height="match_parent"
 
−
    tools:context=".Adaptadores.UD04_02_Spinners">
 
−
 
 
−
    <Spinner
 
−
        android:id="@+id/spnLista_UD04_03_Spinner"
 
−
        android:layout_width="wrap_content"
 
−
        android:layout_height="wrap_content"
 
−
        android:layout_marginBottom="8dp"
 
−
        android:layout_marginEnd="8dp"
 
−
        android:layout_marginStart="8dp"
 
−
        android:layout_marginTop="8dp"
 
−
        app:layout_constraintBottom_toBottomOf="parent"
 
−
        app:layout_constraintEnd_toEndOf="parent"
 
−
        app:layout_constraintStart_toStartOf="parent"
 
−
        app:layout_constraintTop_toTopOf="parent" />
 
−
</android.support.constraint.ConstraintLayout>
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
*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.
 
−
 
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="22-30" >
 
−
package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 
−
 
 
−
import android.app.Activity;
 
−
import android.os.Bundle;
 
−
import android.view.View;
 
−
import android.widget.AdapterView;
 
−
import android.widget.ArrayAdapter;
 
−
import android.widget.Spinner;
 
−
import android.widget.TextView;
 
−
import android.widget.Toast;
 
−
 
 
−
import java.util.ArrayList;
 
−
 
 
−
import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 
−
 
 
−
public class UD04_03_Spinners extends Activity {
 
−
 
 
−
    private void cargarLista(){
 
−
 
 
−
        Spinner spinFroitas = (Spinner) findViewById(R.id.spnLista_UD04_03_Spinner);
 
−
 
 
−
        ArrayList<String> animais = new ArrayList<String>();
 
−
 
 
−
        animais.add("CABALLOS");
 
−
        animais.add("GATITOS");
 
−
        animais.add("PERROS");
 
−
        animais.add("RATONES");
 
−
 
 
−
        // Enlace do adaptador cos datos
 
−
        ArrayAdapter<String> adaptador = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, animais);
 
−
 
 
−
        // Enlace do adaptador co Spinner do Layout.
 
−
        spinFroitas.setAdapter(adaptador);
 
−
 
 
−
        // Escoitador
 
−
        spinFroitas.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
 
−
            @Override
 
−
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
 
−
                //Toast.makeText(getBaseContext(), "Seleccionaches: " + parent.getItemAtPosition(pos), Toast.LENGTH_LONG).show();
 
−
                Toast.makeText(getBaseContext(), "Seleccionaches: " + ((TextView) view).getText(), Toast.LENGTH_LONG).show();
 
−
 
 
−
            }
 
−
 
 
−
            @Override
 
−
            public void onNothingSelected(AdapterView<?> arg0) {
 
−
                // TODO Auto-generated method stub
 
−
            }
 
−
        }); // Fin da clase anónima
 
−
 
 
−
    }
 
−
 
 
−
 
 
−
    @Override
 
−
    protected void onCreate(Bundle savedInstanceState) {
 
−
        super.onCreate(savedInstanceState);
 
−
        setContentView(R.layout.activity_ud04_03__spinners);
 
−
 
 
−
        cargarLista();
 
−
    }
 
−
}
 
−
</syntaxhighlight >
 
−
 
 
−
*'''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.
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
==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 [http://wiki.cifprodolfoucha.es/index.php?title=PDM_Creando_proxecto_base xa vimos na creación do proxecto base].
 
−
 
 
−
 
−
<br />
 
−
* 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 <u>noso propio adaptador</u>.
 
−
 
 
−
* Nesta práctica creamos un layout formado por unha imaxe e un texto para cada elemento da lista do spinner.
 
−
[[Imagen:PDM_adaptador_10.jpg|400px|center]]
 
−
 
 
−
 
 
−
 
 
−
 
 
−
* 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
 
−
<syntaxhighlight lang="xml" line enclose="div" highlight="">
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 
−
    xmlns:app="http://schemas.android.com/apk/res-auto"
 
−
    android:layout_width="match_parent"
 
−
    android:layout_height="match_parent">
 
−
 
 
−
    <ImageView
 
−
        android:id="@+id/imgVImaxen_UD04_04_Spinners"
 
−
        android:layout_width="wrap_content"
 
−
        android:layout_height="wrap_content"
 
−
        android:layout_weight="1"
 
−
        />
 
−
 
 
−
    <TextView
 
−
        android:id="@+id/txtTexto_UD04_04_Spinners"
 
−
        android:layout_width="wrap_content"
 
−
        android:layout_height="wrap_content"
 
−
        android:layout_weight="2"
 
−
        android:text="TextView" />
 
−
</LinearLayout>
 
−
</syntaxhighlight>
 
−
: Como vemos, estamos a definir un layout cun Imageview e un TextView. Pero <u>poderíamos poñer calquera lauyout con calquera número de elementos e deseño</u>.
 
−
 
 
−
 
 
−
 
 
−
: Partimos dun exercicio anterior onte xa tiñamos definidos nun array os datos do exercicio:
 
−
<syntaxhighlight lang="xml" line enclose="div" highlight="">
 
−
<?xml version="1.0" encoding="utf-8"?>
 
−
<resources>
 
−
 
 
−
    <string-array name="planetas_UD02_01_spinner">
 
−
        <item>Mercurio</item>
 
−
        <item>Venus</item>
 
−
        <item>Terra</item>
 
−
        <item>Marte</item>
 
−
        <item>Xúpiter</item>
 
−
        <item>Saturno</item>
 
−
        <item>Urano</item>
 
−
        <item>Neptuno</item>
 
−
    </string-array>
 
−
 
 
−
</resources>
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
* Agora crearemos o Adaptador.
 
−
 
 
−
<gallery caption="Creando un adaptador propio" widths="350" heights="300px" perrow="2">
 
−
Image:PDM_adaptador_5.jpg| Creamos unha nova Java Class.
 
−
Image:PDM_adaptador_6.jpg| Dámoslle un nome á clase e <u>facemos que herde da clase ArrayAdapter</u>.No noso exemplo chámase '''Adaptador_UD04_04_Spinners'''.
 
−
Image:PDM_adaptador_7.jpg| Aparecerá un erro.
 
−
Image:PDM_adaptador_8.jpg| Debemos situarnos sobre a liña con erro e premer Alt+Enter. Escolleremos a opción de 'Create constructor...'.
 
−
Image:PDM_adaptador_9.jpg| Dentro dos construtores posibles escollemos o primeiro. Isto da igual xa que o construtor o imos personalizar ás nosas necesidades.
 
−
</gallery>
 
−
 
 
−
: Despois de facer o anterior teremos un código coma isto:
 
−
: '''Arquivo:''' Adaptador_UD04_04_Spinners
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="">
 
−
public class Adaptador_UD04_04_Spinners extends ArrayAdapter {
 
−
   
 
−
    public AdaptadorPrueba(@NonNull Context context, int resource) {
 
−
        super(context, resource);
 
−
    }
 
−
}
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
* 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:
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="8">
 
−
public class Adaptador_UD04_04_Spinners extends ArrayAdapter {
 
−
 
 
−
    int[] imaxes;  // Lista de imaxes a cargar. Lembra que en res todo son números  Se foran url poderíamos cambialo por String[]
 
−
    String[] textos;
 
−
    Context mContext;
 
−
 
 
−
    public Adaptador_UD04_04_Spinners(@NonNull Context context, int[]imaxes,String[]textos) {
 
−
        super(context, R.layout.spinner_ud04_04);      // Enviamos o layout que imos utilizar
 
−
 
 
−
        this.imaxes = imaxes;
 
−
        this.textos = textos;
 
−
        this.mContext = context;
 
−
    }
 
−
   
 
−
}
 
−
</syntaxhighlight>
 
−
 
 
−
: 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). <u>E o view que visualiza o elemento escollido da lista</u>.
 
−
:* 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). No exemplo imos amosar o mesmo que en getView (pero non tería por qué ser así).
 
−
 
 
−
: Fixarse que no caso dos métodos que devolven un view, podemos facer nos un dinamicamente e devolvelo.
 
−
: Por exemplo, se fago isto:
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="8">
 
−
    @Override
 
−
    public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
 
−
        TextView proba = new TextView(mContext);
 
−
        proba.setText("OOOOOOOO");
 
−
        return proba;
 
−
    }
 
−
</syntaxhighlight>
 
−
 
 
−
: Aparece isto:
 
−
[[Imagen:PDM_adaptador_11.jpg|400px|center]]
 
−
: 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 [https://stackoverflow.com/questions/13433874/difference-between-getview-getdropdownview-in-spinneradapter 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í:
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="3,8">
 
−
    @Override
 
−
    public int getCount() {
 
−
        return textos.length;      // Poderíamos poñer tamén o número de imaxes.
 
−
    }
 
−
 
 
−
    @Override
 
−
    public View getDropDownView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
 
−
        return getView(position,convertView,parent);
 
−
    }
 
−
 
 
−
    @NonNull
 
−
    @Override
 
−
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
 
−
        return super.getView(position, convertView, parent);
 
−
    }
 
−
</syntaxhighlight>
 
−
 
 
−
:* 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.
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
* Agora ven o máis importante, que é crear o view que conforma o elemento seleccionado no Spinner:
 
−
[[Imagen:PDM_adaptador_12.jpg|400px|center]]
 
−
 
 
−
: 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 [https://developer.android.com/reference/android/view/View#setTag(java.lang.Object) método setTag] xa comentado nesta wiki.
 
−
 
 
−
: Ese obxecto que aparece como parámetro (convertView) representa o conxunto de elementos gráficos que conforman cada fila do spinner.
 
−
: A primeira vez que se chama, ese obxecto vale 'null' e debemos de facer que sexa igual ao layout no que definimos a imaxe e o texto que conforman cada elemento da lista.
 
−
: A segunga e seguintes veces, ese dato xa virá co layout asociado.
 
−
 
 
−
 
 
−
* 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':
 
−
::<syntaxhighlight lang="java" line enclose="div" highlight="">
 
−
            LayoutInflater mInflater = (LayoutInflater) mContext.
 
−
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
−
            convertView = mInflater.inflate(R.layout.spinner_ud04_04, parent, false);
 
−
</syntaxhighlight>
 
−
: 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.
 
−
: Como dixemos antes, isto soamente hai que facelo se o convertView ven cun valor null.
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="4-9">
 
−
    @Override
 
−
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
 
−
 
 
−
        if (convertView == null) {
 
−
 
 
−
            LayoutInflater mInflater = (LayoutInflater) mContext.
 
−
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
−
            convertView = mInflater.inflate(R.layout.spinner_ud04_04, parent, false);
 
−
        }
 
−
        .............
 
−
    }
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
 
 
−
* '''Segundo''', debemos pasar os datos a cada un dos elementos gráficos que se atopan no obxecto 'convertView'.
 
−
: Para iso podemos empregar o método findViewById no convertView. O único que temos que facer é buscar cada compoñente gráfico e asociarlle o dato que sabemos cal é polo parámetro 'int position', que indica a posición do elemento da lista seleccionado.
 
−
 
 
−
::<syntaxhighlight lang="java" line enclose="div" highlight="10-11,13">
 
−
    @Override
 
−
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
 
−
 
 
−
        if (convertView == null) {
 
−
 
 
−
            LayoutInflater mInflater = (LayoutInflater) mContext.
 
−
                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
−
            convertView = mInflater.inflate(R.layout.spinner_ud04_04, parent, false);
 
−
        }
 
−
        ((ImageView)convertView.findViewById(R.id.imgVImaxen_UD04_04_Spinners)).setImageResource(imaxes[position]);
 
−
        ((TextView) convertView.findViewById(R.id.txtTexto_UD04_04_Spinners)).setText(textos[position]);
 
−
 
 
−
        return convertView;
 
−
 
 
−
    }
 
−
 
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
: <u>Nota:</u> Lembrar que como [https://wiki.cifprodolfoucha.es/index.php?title=ImageView xa vimos no caso do ImageView], podemos empregar os métodos getTag() e setTag() para enviar datos e asocialos a un view.
 
−
 
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
* 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
 
−
<syntaxhighlight lang="java" line enclose="div" highlight="">
 
−
package es.cursoandroid.cifprodolfoucha.aprendiendo.Adaptadores;
 
−
 
 
−
import android.app.Activity;
 
−
import android.os.Bundle;
 
−
import android.widget.Spinner;
 
−
 
 
−
import es.cursoandroid.cifprodolfoucha.aprendiendo.R;
 
−
 
 
−
public class UD04_04_Spinners extends Activity {
 
−
 
 
−
    private void cargarLista(){
 
−
        String datos[] = getResources().getStringArray(R.array.planetas_UD02_01_spinner);
 
−
        int[] imaxes = new int[datos.length];
 
−
      for(int cont=0;cont<datos.length;cont++){
 
−
          imaxes[cont]=R.drawable.ok;
 
−
      }
 
−
 
 
−
        Spinner lista = findViewById(R.id.spnLista_UD04_04_Spinner);
 
−
 
 
−
        Adaptador_UD04_04_Spinners meuAdaptador = new Adaptador_UD04_04_Spinners(this,imaxes,datos);
 
−
        lista.setAdapter(meuAdaptador);
 
−
 
 
−
    }
 
−
 
 
−
    @Override
 
−
    protected void onCreate(Bundle savedInstanceState) {
 
−
        super.onCreate(savedInstanceState);
 
−
        setContentView(R.layout.activity_ud04_04__spinners);
 
−
 
 
−
        cargarLista();
 
−
    }
 
−
}
 
−
 
 
−
</syntaxhighlight>
 
−
 
 
−
 
 
−
 
 
−
 
 
−
<br />
 
−
 
 
−
 
 
−
 
 
−
<br> -- [[Usuario:angelfg|Ángel D. Fernández González]] e [[Usuario:Carrion|Carlos Carrión Álvarez]] -- (2018).
 

Revisión actual del 11:53 21 nov 2020