Inicio Android Interfaz de usuario en Android: Controles de selección (I)

Interfaz de usuario en Android: Controles de selección (I)

por sgoliver

Actualizado: Mayo 2020

Una vez repasados los controles básicos (IIIIII) que podemos utilizar en nuestras aplicaciones Android, vamos a dedicar los próximos artículos a describir los diferentes controles de selección disponibles en la plataforma. Al igual que en otros frameworks Android dispone de diversos controles que nos permiten seleccionar una opción dentro de una lista de posibilidades. Así, podremos utilizar por ejemplo listas desplegables (Spinner), y listas fijas y tablas (RecyclerView).

En este primer artículo dedicado a los controles de selección vamos a describir un elemento importante y común a todos ellos, los adaptadores, y lo vamos a aplicar al primer control de los indicados, las listas desplegables.

Adaptadores en Android (adapters)

Un adaptador representa algo así como una interfaz común al modelo de datos que existe por detrás de todos los controles de selección que hemos comentado. Dicho de otra forma, todos los controles de selección accederán a los datos que contienen a través de un adaptador.

Además de proveer de datos a los controles visuales, el adaptador también será responsable de generar a partir de estos datos las vistas específicas que se mostrarán dentro del control de selección. Por ejemplo, si cada elemento de una lista estuviera formado a su vez por una imagen y varias etiquetas, el responsable de generar y establecer el contenido de todos estos «sub-elementos» a partir de los datos será el propio adaptador.

Android proporciona de serie varios tipos de adaptadores sencillos, aunque podemos extender su funcionalidad fácilmente para adaptarlos a nuestras necesidades. Los más comunes son los siguientes:

  • ArrayAdapter. Es el más sencillo de todos los adaptadores, y provee de datos a un control de selección a partir de un array de objetos de cualquier tipo.
  • SimpleAdapter. Se utiliza para mapear datos sobre los diferentes controles definidos en un fichero XML de layout.
  • SimpleCursorAdapter. Se utiliza para mapear las columnas de un cursor abierto sobre una base de datos sobre los diferentes elementos visuales contenidos en el control de selección.

Para no complicar excesivamente los tutoriales, por ahora nos vamos a conformar con describir la forma de utilizar un ArrayAdapter con los diferentes controles de selección disponibles.

Veamos cómo crear un adaptador de tipo ArrayAdapter para trabajar con un array genérico de kotlin:

val datos = arrayOf("Elem1", "Elem2", "Elem3", "Elem4", "Elem5")
val adaptador = 
        ArrayAdapter(this, android.R.layout.simple_spinner_item, datos)

Comentemos un poco el código. Sobre la primera línea no hay nada que decir, es tan sólo la definición del array que contendrá los datos a mostrar en el control, en este caso un array sencillo con cinco cadenas de caracteres. En la segunda línea creamos el adaptador en sí, al que pasamos 3 parámetros:

  1. El contexto, que normalmente será simplemente una referencia a la actividad donde se crea el adaptador.
  2. El ID del layout sobre el que se mostrarán los datos del control. En este caso le pasamos el ID de un layout predefinido en Android (android.R.layout.simple_spinner_item), formado únicamente por un control TextView, pero podríamos pasarle el ID de cualquier layout personalizado de nuestro proyecto con cualquier estructura y conjunto de controles, más adelante veremos cómo.
  3. El array que contiene los datos a mostrar.

Con esto ya tendríamos creado nuestro adaptador para los datos a mostrar y ya tan sólo nos quedaría asignar este adaptador a nuestro control de selección para que éste mostrase los datos en la aplicación.

Una alternativa a tener en cuenta si los datos a mostrar en el control son estáticos sería definir la lista de posibles valores como un recurso de tipo string-array. Para ello, primero crearíamos un nuevo fichero XML en la carpeta /res/values llamado por ejemplo valores_array.xml e incluiríamos en él los valores seleccionables de la siguiente forma:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="valores_array">
        <item>Elem1</item>
        <item>Elem2</item>
        <item>Elem3</item>
        <item>Elem4</item>
        <item>Elem5</item>
    </string-array>
</resources>

Tras esto, a la hora de crear el adaptador, utilizaríamos el método createFromResource() para hacer referencia a este array XML que acabamos de crear:

val adaptador = 
    ArrayAdapter.createFromResource(this, R.array.valores_array, 
        android.R.layout.simple_spinner_item)

Control Spinner [API]

Las listas desplegables en Android se llaman Spinner. Funcionan de forma similar a cualquier control de este tipo, el usuario selecciona la lista, se muestra una especie de lista emergente al usuario con todas las opciones disponibles y al seleccionarse una de ellas ésta queda fijada en el control. Para añadir una lista de este tipo a nuestra aplicación podemos utilizar el código siguiente:

<Spinner android:id="@+id/cmbOpciones"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

Poco vamos a comentar de aquí ya que lo que nos interesan realmente son los datos a mostrar. En cualquier caso, las opciones para personalizar el aspecto visual del control (fondo, color y tamaño de fuente, …) son las mismas ya comentadas para los controles básicos.

Para enlazar nuestro adaptador (y por tanto nuestros datos) a este control utilizaremos el siguiente código kotlin:

cmbOpciones = findViewById(R.id.cmbOpciones)

val adaptador = 
    ArrayAdapter.createFromResource(this, R.array.valores_array, 
        android.R.layout.simple_spinner_item)

adaptador.setDropDownViewResource(
    android.R.layout.simple_spinner_dropdown_item)

cmbOpciones.adapter = adaptador

Comenzamos como siempre por obtener una referencia al control a través de su ID. Y en la última línea asignamos el adaptador al control mediante el método setAdapter(). ¿Y la penúltima línea para qué es? Cuando indicamos en el apartado anterior cómo construir un adaptador vimos cómo uno de los parámetros que le pasábamos era el ID del layout que utilizaríamos para visualizar los elementos del control. Sin embargo, en el caso del control Spinner, este layout tan sólo se aplicará al elemento seleccionado en la lista, es decir, al que se muestra directamente sobre el propio control cuando no está desplegado. Sin embargo, antes indicamos que el funcionamiento normal del control Spinner incluye entre otras cosas mostrar una lista emergente con todas las opciones disponibles. Pues bien, para personalizar también el aspecto de cada elemento en dicha lista emergente tenemos el método setDropDownViewResource(ID_layout), al que podemos pasar otro ID de layout distinto al primero sobre el que se mostrarán los elementos de la lista emergente. En este caso hemos utilizado otro layout predefinido en Android para las listas desplegables (android.R.layout.simple_spinner_dropdown_item), formado por una etiqueta de texto con la descripción de la opción.

Con estas simples lineas de código conseguiremos mostrar un control como el que vemos en la siguiente imagen:

En cuanto a los eventos lanzados por el control Spinner, el más comúnmente utilizado será el generado al seleccionarse una opción de la lista desplegable, onItemSelected. Para capturar este evento se procederá de forma similar a lo ya visto para otros controles anteriormente, asignándole su controlador mediante la propiedad onItemSelectedListener:

cmbOpciones.onItemSelectedListener = object: AdapterView.OnItemSelectedListener {
    override fun onNothingSelected(parent: AdapterView<*>) {
        lblSeleccion.text = "Sin selección"
    }

    override fun onItemSelected(parent: AdapterView<*>, view: View?, position: Int, id: Long) {
        val pos = parent.getItemAtPosition(position)
        lblSeleccion.text = "Seleccionado: $pos"
    }
}

A diferencia de ocasiones anteriores, para este evento definimos dos métodos, el primero de ellos (onItemSelected) que será llamado cada vez que se selecciones una opción en la lista desplegable, y el segundo (onNothingSelected) que se llamará cuando no haya ninguna opción seleccionada (esto puede ocurrir por ejemplo si el adaptador no tiene datos). Además, vemos cómo para recuperar el dato seleccionado utilizamos el método getItemAtPosition() del parámetro AdapterView que recibimos en el evento. Para el ejemplo lo estoy mostrando sobre una etiqueta de texto, lblSeleccion, que también he añadido a la interfaz.

CÓDIGO DEL ARTÍCULO: Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la pagina del curso en GitHub.

También te puede interesar

39 comentarios

Interfaz de usuario en Android: Controles de selección (II) | sgoliver.net blog 07/09/2010 - 12:02

[…] el artículo anterior ya comenzamos a hablar de los controles de selección en Android, empezando por explicar el […]

Responder
Interfaz de usuario en Android: Controles de selección (IV) | sgoliver.net blog 11/09/2010 - 23:07

[…] los dos controles de selección más comunes en cualquier interfaz gráfica, como son las listas desplegables (Spinner) y las listas “fijas” (ListView), tanto en su versión básica como optimizada, en este […]

Responder
Desarrollo en Android | sgoliver.net blog 11/09/2010 - 23:18

[…] Interfaz de usuario en Android: Controles de selección (I) […]

Responder
Jordi 23/12/2010 - 12:22

Hola,

Primero de todo agradecer el curro de hacer el tutorial, es genial!

Sobre este tema en concreto de Spinner, cuando defines el Adapter

ArrayAdapter adaptador =
new ArrayAdapter(this,
android.R.layout.simple_spinner_item, datos);

Haces referencia a un layout.

Además, defines un objeto spinner con id «CmbOpciones». Y referencias la opcióin DropDrow al «simple_spinner_dropdown_item».

El «simple_spinner_item» no sería el «CmbOpciones»?

Si accedes a ellos mediante R.layout, son LinearLayout o algun otro parecido?

Muchas gracias!

Jordi.

Responder
sgoliver 23/12/2010 - 12:56

Hola Jordi,

CmbOpciones no es un layout xml, es la lista desplegable como tal, el objeto completo, por decirlo de alguna forma.

Por su parte, simple_spinner_item es el layout xml que se va a usar para representar CADA elemento individual de la lista desplegable, es decir, cada linea de la lista por separado. Se puede utilizar cualquier layout que definas tú mismo en la carpeta \res\layout pero para no complicar el ejemplo he utilizado uno que ya viene predefinido en el SDK de Android (por eso comienza por «android.R.layout», en vez de «R.layout»).

Saludos.

Responder
Juan Ospina 12/01/2011 - 10:47

Muchas gracias!!! excelente informacion, me ha servido muchisimo

Responder
Alexis 16/03/2011 - 4:49

Hola amigo, antes que nada mil gracias por estos tutoriales, he tratado de aplicar este ejemplo pero me lanza error, el codigo completo del main.java es:

package com.prueba.listview;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.Spinner;

public class main extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

final String[] datos =
new String[]{«Elem1″,»Elem2″,»Elem3″,»Elem4″,»Elem5»};

ArrayAdapter adaptador =
new ArrayAdapter(this,
android.R.layout.simple_spinner_item, datos);

final Spinner cmbOpciones = (Spinner)findViewById(R.id.CmbOpciones);

adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cmbOpciones.setAdapter(adaptador);
}

Pero me salta erro en las ultimas dos lineas, el error es el siguiente:

Multiple markers at this line
– Syntax error on token «setDropDownViewResource», Identifier expected after
this token
– Syntax error on token «.», … expected
– Syntax error on token «setDropDownViewResource», Identifier expected after
this token

que podra ser?

saludos

Responder
Camilo Puentes 28/03/2011 - 4:22

saludos Quiero Agradecerle por este aporte tan completo
y quisiera preguntarle si ha intentado hacer un spinner con registros de una base de datos en sqlite sobre android y si lo ha intentado cual es la forma para hacerlo

gracias
Espero su respuesta

Responder
Jlg 31/03/2011 - 12:14

Buen curro y buen toutorial te has currado.

Solo indicarte que tengo el mismo problema que Alexis,
me dan los mismos errores en las 2 últimas líneas.
He buscado y no veo por qué.

Gracias.

Responder
Jlg 31/03/2011 - 12:51

Alexis, ya he visto el error.
Es una cosa muy tona ;)

Tienes que meter el código dentro de onCreate:

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//} <— Este es el problema

final String[] datos =
new String[]{“Elem1″,”Elem2″,”Elem3″,”Elem4″,”Elem5″};

ArrayAdapter adaptador =
new ArrayAdapter(this,
android.R.layout.simple_spinner_item, datos);

final Spinner cmbOpciones = (Spinner)findViewById(R.id.CmbOpciones);

adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cmbOpciones.setAdapter(adaptador);
} // <– Aqui se cierra.
}

Responder
juanes 22/05/2011 - 22:46

hola, me gustaria saber como poner en el Spinner, un texto que diga «seleccione una opcion»…con el prompt me sale este texto, pero cuando el spinner es desplegado…yo necesito que me muestre «seleccione una opcion», pero sin desplegar el spinner..en su estado inicial por decirlo de alguna manera..gracias!!

Responder
Agm 05/06/2011 - 16:40

Hola, el codigo me da dos errores en las siguientes lineas:

final Spinner cmbOpciones = (Spinner)findViewById(R.id.CmbOpciones); // El error aqui es:Cannot cast from View to Spinner

cmbOpciones.setAdapter(adaptador); // El error aqui es: The method setAdapter(ArrayAdapter) is undefined for the type Spinner.

Este es mi codigo:

package net.sgoliver;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class Spinner extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

final String[] datos =
new String[]{«Elem1″,»Elem2″,»Elem3″,»Elem4″,»Elem5»};

ArrayAdapter adaptador =
new ArrayAdapter(this,
android.R.layout.simple_spinner_item, datos);

final Spinner cmbOpciones = (Spinner)findViewById(R.id.CmbOpciones);

adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cmbOpciones.setAdapter(adaptador);
}}

Alguien sabra donde me estoy equivocando? gracias de antemano

Responder
nise14 15/06/2011 - 22:01

Saludes, excelentes tutoriales, tengo una duda, en un spinner no se puede poner un filtro, es que estoy llenando el spinner desde una base de datos que contiene mas de 1000 registros y es bastante incomodo desplazarse uno por uno, hasta encontrar el qeu necesito.

Responder
Manuel 12/07/2011 - 21:20

@Agm
me ocurre exactamente los mismo que a ti. Le estoy dando vueltas y vueltas y no encuentro la solución.
Lo has solucionado

Responder
Manuel 12/07/2011 - 21:29

@Agm y yo mismo,
me auto respondo, el problema es que la clase se llama Spinner, y genera conflicto.
Cambia el nombre. y funciona.

Responder
enmanuel 23/10/2011 - 14:57

Buenos dias

exelente Tutorial gracias por dedicar tiempo,me gustaría que usted colocara una pagina explicando como colocar diferente imágenes en ListView.

gracias

Responder
Jajoo 28/10/2011 - 23:24

HolA!

Gracias como siempre :) Podrías dejar el enlace de la descarga del código como en el resto de los tutoriales? muchas gracias.

Responder
poiel2010 05/01/2012 - 0:29

El interes de andoid me ha despertado desde el año pasado, y me parece que para empezar esta muy bien, aunque soy estudiante de redes y telecomunicaciones. Muchas gracias por compartir sus conocimientos con tanta gente que estamos en esto, con deseos de mejorar personalmente y hacer un aporte a nuestra sociedad.

Responder
Humberto 30/01/2012 - 22:42

Muy Buen tutorial n__n Una duda: ¿Se puede Poner un ScrollBar (Barra de Desplazamiento) al Spinner? Esto para poder desplazarse y no aparesca todo el Menu de Opciones en la Pantalla, es bastante incomodo /: que aparescan todos xD es como ponerle un tope a los Items que hayamos puesto /:

Responder
sgoliver 31/01/2012 - 12:03

Hola Humberto,

te animo a que expongas tu consulta en el foro de la web (http://www.sgoliver.net/foro) de forma que otros usuarios también puedan ayudarte. Saludos.

Responder
Raymundo Castillo 11/02/2012 - 9:10

buen día, antes que nada muchas gracias por estos excelentes cursos, tengo una duda, quisiera saber si en lugar de poblar el spinner con un array de String[] puedo hacerlo con un List ?. saludos!

Responder
Luis Alejandro 14/01/2013 - 21:10

Hola sgoliver, quisiera comentar que aproposito he ignorado el fragmento de codigo «adaptador.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);» y no noto ninguna diferencia, puesto o no puesto funciona de igual manera, quisiera saber porque y cual es la funcion de esta linea de codigo, gracias!

Responder
David 24/02/2013 - 13:07

En este blog, se están COPIANDO tus contenidos.
Ejemplo: optimizarsinmas.blogspot.com.es/2011/03/mi-cuaderno-android-controles-de.html

Responder
admin 25/02/2013 - 9:15

Gracias por el aviso David.

Responder
oso 27/04/2013 - 22:13

Estimado muy bueno el tutorial pero tengo una consulta llevo varioa dias tratando de hacer que el spinner que yo tengo al momento de cargar me carge seleccionado un valor ejemplo tengo un appiner con los meses y quiero cuando aparesca el spinner salga seleccionado el mes actual seria de mucha ayuda si me puedes ayudar a solucionar el problema de antemano muchas gracias

Responder
Omar A 20/05/2013 - 7:19

Buenas, primero quisiera agradecerte y felicitarte por tan buenos tutoriales que hacen, espero que sigan asi, bueno quisiera preguntarles algo, espero que me entiendan lo que quiero…

Bueno en este tutorial lo entendi todo, el problema es que al usar la alternativa 2, creando el arreglo en un xml yo le puse valores diferentes.

Ya que aqui nada mas pone como darle valores a datos desde el MainActivity, de esto la siguiente linea de codigo

final String[] datos = new String[]{«Elem1″,»Elem2″,»Elem3″,»Elem4″,»Elem5»};

Me gustaria saber como darle los valores a datos desde el arreglo o el xml que se creo con lo valores para que esta linea de codigo

lblMensaje.setText(«Seleccionado: » + datos[position]);

Me de los datos que estan en el xml, ya que si se deja asi me da los valores Elem1, Elem2.. etc, y no los que tengo en el valores_aray.xml

De atenmano muchas gracias y espero que me hallan entendido lo que preguntaba :D

Responder
js 16/09/2013 - 21:55

tengo cargado un spinner con una simpleadapter.. cargos de un persona:
id cargo
15 administrador
20 gerente
22 contador..

ArrayList<HashMap> registros = new ArrayList<HashMap>();

cursor = myDataBase.rawQuery(sentencia, null);
if (cursor.moveToFirst())
do {
HashMap Data = new HashMap();
Data.put(«_id», «» + cursor.getInt(0));
Data.put(«cargo», cursor.getString(1));
registros.add(Data);
} while (cursor.moveToNext());

SimpleAdapter adapter = new SimpleAdapter(myContext, registros,
android.R.layout.simple_spinner_item,
new String[] { «cargo» }, new int[] { android.R.id.text1 });

spinnerAreas.setAdapter(adapter);

en mi proyecto consulto los datos de un de una persona de mi base de datos.. nombre, direccion… id_cargo…etc
necesito q el spinner quede ubicado en el cargo que tiene la persona.
quedaría muy agradecido su me pudieran colaborar con esto

Responder
Palomita 26/11/2013 - 20:38

Que tal un saludo a todos!!

Bueno espero me puedan ayudar, desde ya gracias!!, mi problema es el siguiente: quiero sincronizar dos spinner, es decir, cuando se seleccione un item con indice X del spinner1 automaticamente el spinner2 cambie su indice al mismo del spinner1.

Gracias!!

Responder
Jose 12/12/2013 - 16:10

Hola!

estoy iniciandome en android y necesito hacer un spinner para mi aplicación. Me estoy basando en tu ejemplo pero tengo una duda.

Cuando creas el adaptador para luego hacer referencia al archivo.xml que va en la carpeta menú:

ArrayAdapter adapter = ArrayAdapter.createFromResource(this,
R.array.valores_array, android.R.layout.simple_spinner_item);

Cuando compilas salta un warning que dice que «adapter» nunca se usa. Me podeis ayudar a entender esto??. Gracias de ante mano.

Responder
Jose 12/12/2013 - 16:13

Perdón, me he equivocado de carpeta, quería decir values.

Responder
Jose 12/12/2013 - 17:27

Si estoy en lo cierto nunca se mostrara el contenido del archivo valores_array

Responder
Arias 04/04/2014 - 23:14

Que tal amigos, estoy siguiedo el curso muy interesante pero este tema lo veo con mas nivel de dificultad, que los anteriores temas y capitulos, bueno espero entenderlos todos y comprenderlos de la mejor manera…. saludos…. atte Arias

Responder
kagome 22/05/2015 - 2:18

Hola primero que nada tengo una duda , me podrian decir como puedo utilizar un spinner con multipantallas.
Lo que tiene que hacer el spinner es que al darle click a un elemento me lleve a otra pantalla ,es un trabajo para la escuela solo que tengo que hacerlo con un juego de cartas si me ayudan se los agradeceria bueno eso es todo gracias…..

Responder
Actionbar / Appbar / Toolbar en Android (III) | sgoliver.net blog 02/06/2015 - 18:28

[…] de los elementos de la lista desplegable y del control en sí, como ya explicamos en el artículo dedicado al control […]

Responder
naye 08/05/2016 - 4:08

gracias muy bueno siempre me han ayudado con mi tareas de android

Responder
Mario German 26/08/2016 - 22:57

Un excelente tutorial, gracias por compartir tus conocimientos con todos nosotros, tengo la siguiente duda: Tengo una base de datos ya creada y la cual se muestra en un Recyclerview con valores como Id, Nombre y Telefono y quiero colocar un spinner el cual me deje colocar una serie de valores, como puedo hacer para que cuando le de click en un valor del spinner se guarde dicho valor en SQLite y despues cuando vuelva a entrar a la actividad me muestre el valor guardado, agradezco toda la ayuda que me puedas brindar. Gracias.

Responder
Mario German 27/08/2016 - 13:02

Hola, muchas gracias por tu aporte, tengo la siguiente duda tengo un spinner el cual puedo seleccionar un valor, mi idea es que cuando lo seleccione quede guardado en una base de datos sqlite y que cuando vuelva ingresar a la actividad aparezca el valor que yo seleccione, tienes idea de cómo debo hacerlo, agradezco tu aporte.

Responder
Neomar Blanco 09/08/2017 - 19:55

Buenas tardes, en mi app tengo un spinner (desplegable) con una lista de item cargados en un String-array, el detalla es que al cargar mi lista de item varios sobrepasan el espacio (width) de mi spinner, por lo que las palabras se cortan y no se muestran, lo que busco de hacer es que mis item se coloquen en 2 lineas si sobre pasa ese limite.. Mi array es el siguiente

EXPENDIO DE ALIMENTOS O BIENES VENCIDOS
IMPORTACIÓN DE BIENES NOCIVOS PARA LA SALUD
USURA EN OPERACIONES DE FINANCIAMIENTO
CORRUPCIÓN ENTRE PARTICULARES

Los 3 primeros elementos sobrepasan el limire de mi spinner y no se visualiza el texto completo

el codigo de mi spinner es el siguente

Responder
Actionbar / Appbar / Toolbar en Android (III): Filtros y Tabs | sgoliver.net 30/07/2020 - 20:07

[…] de los elementos de la lista desplegable y del control en sí, como ya explicamos en el artículo dedicado al […]

Responder

Responder a sgoliver Cancelar respuesta

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. Aceptar Más Información

Política de Privacidad y Cookies