Listas de datos

Una lista es una forma de guardar información relacionada, por ejemplo: teléfonos de una agenda, movimientos de una cuenta bancaria, usuarios de una aplicación, la lista de la compra, etc.
En este capítulo vamos a aprender a usarlas.

 Introducción

Una lista es una forma de guardar información relacionada, por ejemplo: teléfonos de una agenda, movimientos de una cuenta bancaria, usuarios de una aplicación, la lista de la compra, etc.
Al igual que hemos hecho con las variables numéricas o de texto, podemos crear una lista y asignarle un nombre, por ejemplo: "lista_colores". Dentro de una lista podemos guardar distintas cosas, por ejemplo: textos, números, colores, otras listas, etc. Sin embargo, dentro de una misma lista únicamente puede haber datos de un único tipo.
A cada dato que guardamos en la lista le acompaña un índice que nos indica la posición que ocupa dentro de la lista. Este índice lo añade AppInventor de forma automática. Por ejemplo, al añadir el primer dato de una lista, AppInventor le asignará el número de índice 1, al segundo dato el número 2, etc.
Usando este índice podemos recuperar el dato que ocupa esa posición en la lista. Usando un bucle como los que hemos visto antes podemos recorrer una lista desde el principio hasta el final.

 Listas estáticas

Una lista estática es una lista de datos que creamos dentro de nuestro programa pero que no cambia mientras nuestro programa está funcionando. Es decir, los valores de la lista permanecen estáticos.
Podemos usar una lista estática para guardar datos que queremos usar de una forma más cómoda, por ejemplo: las preguntas y respuestas de un programa de adivinanzas.
Vamos a verlo con un ejemplo.
En este caso vamos a crear dos listas. La primera tendrá nombres y la segunda colores. Vamos a usar varios botones para aprender a recuperar datos de una lista y a usarlos de varias maneras.
Crea un proyecto nuevo y llámalo "listas_estaticas"
Cambia la propiedad AlignHorizontal del componente screen por Center.
Añade un componente HorizontalArragement y mete dentro una etiqueta y un textbox.
En la etiqueta cambia el texto por "índice".
Cambia el nombre del textbox por indice.
Debajo del componente HorizontalArragement añade un componente ListPicker.
Cambia el texto del ListPicker por "Lista de nombres". Deja el nombre del componente como está.
Por último añade una etiqueta debajo de todo y llámala etiqueta. Puedes borrar el texto de la etiqueta para que aparezca en blanco.
Vamos al Editor de bloques.
10 Para empezar vamos a crear nuestras dos listas estáticas. Una tendrá nombres y la otra colores.
11 Tal y como hacemos cuando vamos a crear una variable cogemos dos bloques "initialize global" dentro de Built-in/Variables y los ponemos en nuestro programa.
12 A la primera llámala "lista_nombres" y a la segunda "lista_colores"
13 Para crear una lista usamos el bloque "make a list" dentro de Built-in/List. Coge dos de estos bloques y pega cada uno a cada variable.
Ahora vamos a rellenar cada lista con los datos que queremos.
14 Como la primera lista contendrá nombres, crea 5 bloques de texto y pon distintos nombres.
15 Cuando los tengas, pégalos al bloque "make a list" de la variable lista_nombres.
16 Para la lista lista_colores vamos a usar colores. Crea 5 bloques de color distintos y pégalos también al bloque "make a list" de la variable lista_colores.
Ya tenemos nuestras listas creadas. Vamos ahora a ver la primera forma que tenemos de usar nuestras listas.
Ya hemos visto antes cómo usar el componente ListPicker. Vamos a usarlo ahora para ver cómo podemos usar una lista y este componente dentro de nuestros programas.
17 Dentro del componente ListPicker en Screen1, coge el evento "ListPicker.BeforePicking" 
18 Ahora coge el bloque "set ListPicker.Elements to" y ponlo dentro.
19 Pega a este bloque la variable "get lista_nombres" que encontrarás en Built-in/Variables.
Ya hemos preparado el componente ListPicker para que trabaje con nuestra lista de nombres.
20 Ahora coge el evento "ListPicker.AfterPicking". Este evento se activará cuando el usuario haya seleccionado un elemento de la lista ListPicker que en nuestro caso hemos preparado para que muestre los nombres de la lista_nombres.
Cuando el usuario haya escogido un elemento de la lista ListPicker vamos a cambiar la etiqueta para que nos muestre cual ha sido.
21 Coge el bloque "set etiqueta.Text" y ponlo dentro del evento .AfterPicking.
22 Dentro de Built-in/List coge el bloque "select list item" y pégalo al bloque ".Text"
Este bloque nos permite recuperar un elemento de una lista usando el índice. Verás que el primer dato que nos pide es la lista (list) de la cual queremos obtener el elemento. El segundo dato que nos pide es precisamente el número del índice en el cual se encuentra el dato que queremos recuperar.
Ya hemos visto que cuando usamos un componente ListPicker al usuario se le presenta una ventana con una lista de elementos entre los que puede elegir uno. La primera vez que usamos este componente lo usamos para que el usuario eligiese el género (hombre o mujer) 
¿recuerdas?
Cuando el usuario selecciona un elemento del componente ListPicker podemos saber qué elemento es el que ha seleccionado usando el bloque "ListPicker.Selection". Este bloque nos devuelve exactamente el dato que el usuario ha seleccionado, por lo que usando este bloque directamente nos valdría.
Otra forma de hacerlo es usando el bloque "ListPicker.SelectionIndex". Este bloque, en lugar de devolvernos directamente el dato que buscamos, nos devuelve el número del índice; es decir, si el usuario ha seleccionado el primero nos devolverá un 1, si ha seleccionado el segundo nos devolverá un 2, etc. Podemos por lo tanto usar este bloque para buscar en nuestra lista_nombres el nombre que corresponde con ese índice.
23 Pega en el espacio list nuestra variable lista lista_nombres. 
24 Pega en el espacio index el bloque ListPicker.SelectionIndex. 
25 Prueba tu programa.
Verás que si seleccionas el primer nombre de la lista, el bloque .SelectionIndex nos devolverá un 1. Usando el bloque "select list item" buscamos el dato que corresponde con el índice 1 y nos devolverá el nombre que está en esa posición.
26 Vamos a verlo con otro ejemplo. Vuelve al Diseñador.
27 Añade un botón más debajo del anterior "Lista de nombres" pero antes de la etiqueta.

29 Cambia el nombre del botón por boton_buscar_nombre y cambia el texto del botón por "buscar nombre". 
Lo que vamos a hacer ahora es usar el campo indice que hemos creado antes para buscar un nombre en concreto según su índice.
29 Coge el evento .Click de este botón que acabamos de crear.
30 Duplica el bloque "set etiqueta.Text to" que hemos usado antes y ponlo dentro.
31 Borra el bloque ListPicker.SelectionIndex que usamos antes en el espacio index y cámbialo por un bloque indice.Text que será el dato que meteremos en nuestro textbox.
Ahora prueba tu programa metiendo un número en el índice y verás como tu programa localiza el nombre que corresponde a ese índice.
¿Qué pasa si pones un número de índice que no existe?
Efectivamente tu programa da un error y termina. Tenemos que controlar que esto no pase así que vamos a ver una forma de evitarlo.
32 Coge un bloque de control if then y ponlo dentro del evento boton_busca_nombre.Click
Mueve el bloque "set etiqueta.Text" que tenemos dentro del evento y mételo dentro del espacio then.
Para controlar que el usuario no mete un índice que no existe tenemos un bloque que se llama "length of list" (tamaño de la lista) que nos dice cuántos elementos hay dentro de una lista. Podemos usar este bloque para controlar que el índice que nos pide el usuario no sea mayor que el número de datos que tenemos y evitar de esta manera que se produzca un error.
Vamos a verlo.
33 Crea un bloque Math <
34 En el primer espacio ponemos el dato con el índice que busca el usuario indice.Text.
35 En el segundo espacio ponemos un bloque "length of list" al cual pegaremos nuestra lista "global lista_nombres"
36 Finalmente pegamos este bloque en el espacio test de nuestro bloque if.
Tiene que quedar así:

Vamos ahora con nuestra lista de colores que vamos a usar para cambiar el color del fondo de la pantalla.
37 Vuelve al Diseñador y añade otro botón más debajo del último botón pero antes de la etiqueta. Cambia el nombre del botón por boton_cambiar_color y el texto por "cambiar color"
38 Volvemos al Editor de bloques.
39 Coge el evento .Click de este nuevo botón.
40 Coge el bloque "set screen1.BackgroundColor" y ponlo dentro del evento.
41 Duplica el bloque "select list item" que usamos antes y pégalo al bloque ".BackgroundColor"
42 Cambia la variable "lista_nombres" por "lista_colores" colocada en list. 
43 Prueba tu programa poniendo un número de índice y pulsando el botón cambiar color. 
Recuerda que el número que pongas tiene que existir o tendrás que volver a añadir un bloque de control if para controlar que tu programa no de error.
Vamos ahora con otra forma de usar listas para controlar el texto de los botones de tu programa. 
44 Vuelve al Diseñador.
45 Añade un botón más al final pero antes de la etiqueta.
46 Cambia el nombre del botón por boton_cambiar_boton y el texto por "cambiar texto botón"
47 Vamos al Editor de bloques
48 Coge el evento .Click de este nuevo botón y ponlo en tu programa.
49 Coge un bloque "set boton_cambiar_boton.Text" y ponlo dentro.
50 Vuelve a duplicar el bloque "select list item" anterior y pégalo al bloque "set boton_cambiar_boton" anterior.
51 Cambia la variable list a "global lista_nombres".
Te tiene que quedar así:

Ahora cuando pongas un número de índice y pulses este botón verás que el texto del botón cambia por el nombre de la lista que corresponde con el índice que has puesto.
Como hemos visto las listas estáticas nos permiten definir con anterioridad los textos, colores y demás información que podemos usar en nuestro programas. Esto nos ahorra espacio y hace que nuestros programas sean más fáciles de manejar. Vamos a ver ahora cómo usar listas dinámicas.

 Listas dinámicas

A diferencia de las listas estáticas las listas dinámicas cambian dentro de nuestro programa, por ejemplo, cuando el usuario añade información en formularios o cuando recuperamos información de una base de datos. Vamos a ver cómo funcionan creando un programa para llevar la lista de la compra.
Comienza un nuevo proyecto y llámalo: "listas_dinamicas"
Cambia la propiedad AlignHorizontal del componente screen por Center.
Añade una etiqueta y cambia el texto por "Mi lista de la compra". Cambia el font para hacer la etiqueta más grande.
Añade un componente HorizontalArragement y mete dentro una etiqueta y un textbox.
En la etiqueta cambia el texto por "Producto: ".
Cambia el nombre del textbox por nuevo_producto.
Añade otro componente HorizontalArragement y mete dentro los siguientes componentes:
Un botón con el nombre boton_anadir y con el texto "añadir"
Un componente ListPicker con el nombre boton_ver y con el texto: "ver lista"
10 Otro componente ListPicker con el nombre boton_borrar y con el texto "borrar"
11 Vamos al Editor de bloques.
12 Empezamos creando nuestra lista que llamaremos lista_productos. Desde Built-in/Variables cogemos un bloque "initialize global" y le pegamos otro bloque "make list" tal y como hemos hecho antes.
13 Coge el evento .Click del botón boton_anadir
14 Coge un bloque "add items to list" de la categoría Built-in/List y ponlo dentro del evento.
15 En el espacio list ponemos nuestra lista "global lista_productos"
16 En el espacio item pondremos el producto que queremos añadir que está en la variable nuevo_producto.Text
17 Por último limpiamos el textbox con un bloque "set_nuevo_producto.text" y le pegamos un bloque de texto en blanco. Hacemos esto para que cada vez que añadamos un nuevo producto, este campo se limpie. 
Ya tenemos solucionada la forma de añadir productos a nuestra lista. Vamos ahora con el botón boton_ver
En realidad ya sabes que boton_ver no es un componente botón sino un componente ListPicker con el que vamos a mostrar la lista de productos. Por lo tanto, lo primero que vamos a hacer es coger el evento boton_ver.BeforePicking para decirle a este componente qué lista queremos que use.
18 Coge el evento boton_ver.BeforePicking
19 Añade dentro un bloque set boton_ver.Elements y pega a este bloque nuestra lista global lista_productos.
De esta forma le estamos diciendo al componente ListPicker lo que queremos que nos enseñe.
20 Pruébalo.
Verás que aparece la lista de productos que vas añadiendo de forma dinámica.
Vamos con el botón que nos permite borrar un elemento de la lista de productos.
21 Coge el evento boton_borrar.BeforePicking.
Como en el caso anterior este componente es en realidad un ListPicker así que vamos a hacer lo mismo que antes.
22 Añade dentro un bloque set boton_borrar.Elements y pega a este bloque nuestra lista "get lista_productos".
Con esto volvemos a mostrar la lista de productos igual que antes, pero en este caso queremos que cuando el usuario seleccione un producto de la lista, este se borre de la lista.
Por lo tanto, necesitamos usar el evento boton_borrar.Afterpicking que es el que me dice cual es el elemento que ha seleccionado el usuario para después borrarlo.
23 Coge el evento boton_borrar.Afterpicking y ponlo en tu programa.
24 Coge un bloque "remove list item" dentro de la categoría Built-in/List. Como antes, en el espacio list ponemos nuestra lista lista_productos
25 Y en el espacio index pondremos el índice del elemento que ha seleccionado el usuario y que está en el bloque boton_borrar.SelectionIndex.
26 Graba tu programa y pruébalo.

 Listas dentro de listas

Ya hemos visto que dentro de una lista podemos guardar texto, números, colores y valores booleanos (verdadero/falso). Ahora vamos a ver cómo podemos meter una lista dentro de otra.
Para nuestro siguiente ejemplo vamos a imaginar que estamos desarrollando una aplicación para viajeros donde pueden encontrar información sobre museos, monumentos, restaurantes, etc. Antes de poder enseñar al usuario la información de cada ciudad queremos preguntarle al usuario por el país que le interesa visitar y una vez sabemos el país, las ciudades más importantes.
Es decir, tendremos una lista de países y una lista de ciudades. La primera lista únicamente contendrá países y la segunda será una lista que a su vez contendrá otras listas. Lo vas a entender mejor al hacer el ejemplo. 
Vamos al Diseñador.
Crea un nuevo proyecto y llámalo: "listas_listas"
Cambia la propiedad AlignHorizontal de la pantalla a "center".
Añade un primer componente ListPicker y llámalo: ListPicker_paises.
Cambia el texto por: "Elige país"
Añade una etiqueta y llámala: etiqueta_pais. Cambia el texto de la etiqueta y déjalo en blanco. Puedes hacer el font más grande.
Añade otro componente ListPicker y llámalo: ListPicker_ciudades 
Cambia el texto del componente por: "Elige una ciudad"
Añade otra etiqueta y llámala: etiqueta_ciudad. Cambia el texto y déjalo en blanco. Cambia también el font para hacerlo más grande.
10 Vamos al Editor de bloques.
11 Primero vamos a crear nuestra lista de países
12 Coge un bloque "initialize global" y cambia el nombre por lista_paises
13 Coge un bloque "make list" y pégalo al anterior bloque.
14 Ahora crea tres bloques de texto y pon en cada uno lo siguiente: "España", "Italia" y "USA"
15 Pégalos al bloque "make list"
16 Vamos con la lista de ciudades.
17 Coge un bloque "initialize global" y cambia su nombre a lista_ciudades
18 Coge ahora un bloque "make list" y pégalo.
19 Vuelve a coger otro bloque "make list" y pégalo al anterior bloque "make list"
Al hacer esto estamos creando una lista dentro de otra.
20 Ahora crea otros tres bloques de texto y cambia el texto por: "Madrid","Barcelona" y "Valencia"
21 Pégalos al segundo bloque "make list" así:

22 Duplica este último bloque "make list" donde tenemos las ciudades de España para crear dos bloques más.
23 Añade estos dos bloques al primer bloque "make list" original.
24 Ahora tenemos que cambiar los nombres de las ciudades de estos dos últimos bloques.
25 Para el segundo cambia las ciudades por las ciudades que corresponden al segundo país de nuestra lista que es Italia. Pon, por ejemplo, "Roma", "Florencia" y "Venecia" Ahora los del país USA. Pon: "New York", "Boston" y "Los Angeles". El resultado es este:

Nuestra lista de países contiene tres países y nuestra lista de ciudades contiene a su vez tres listas, una por cada país que corresponden a las ciudades de cada país. Es importante que el orden de los países corresponda al orden de las listas de ciudades. Por ejemplo, Italia es el segundo país de la lista, por lo tanto, la segunda lista de ciudades corresponde a las ciudades de Italia.
Esto es importante porque cuando le pidamos al usuario el país que quiere visitar sabremos el índice del país. Al saber el índice del país vamos a usar ese mismo índice para buscar las ciudades que corresponden a ese país. Al país índice=3 le corresponde la lista de ciudades con el índice 3, etc. Ahora vamos a verlo más claramente.
26 Vamos a preparar nuestro componente ListPicker para los países. Coge el evento ListPicker_paises.BeforePicking
27 Mete dentro un bloque "set ListPicker_paises.Elements" y pégale la variable (nuestra lista de países) "global lista_paises"
Así le decimos a nuestro componente que queremos que nos enseñe la lista de países.
28 Coge ahora el evento Listpicker_paises.AfterPicking
Recuerda que este evento se activa cuando el usuario ha  elegido un país.
Lo primero que vamos a hacer es actualizar la etiqueta correspondiente.
29 Coge un bloque "set etiqueta_pais.Text" y ponlo dentro.
30 Coge un bloque ListPicker_paises.Selection y pégalo al anterior bloque.
31 Recuerda que el bloque ".Selection" de un componente ListPicker nos devuelve el valor que ha seleccionado el usuario. En este caso, el país que haya elegido.
32 Pruébalo y verás que funciona.
Una vez que sabemos el país tenemos que preparar la segunda lista (lista_ciudades).
33 Coge un bloque set ListPicker_ciudades.Elements y ponlo debajo de la etiqueta anterior.
34 Coge un bloque "select list item" y pégalo al anterior bloque.
Recuerda que este bloque nos permite buscar un elemento dentro de una lista. Lo que necesitamos ahora es buscar la lista que corresponde con el país seleccionado.
35 En el espacio list ponemos un bloque "get lista_ciudades" porque es la lista donde queremos buscar.
36 En el espacio index ponemos un bloque ListPicker_paises.SelectionIndex que nos dice el índice del país que ha seleccionado el usuario. Recuerda que este índice se corresponde con el índice de la lista de ciudades. Por ejemplo, país 1 (España) = lista de ciudades 1 (Madrid,Barcelona,Valencia), país 3 (USA) = lista de ciudades 3 (New York,Boston,Los Angeles), etc.
Sólo nos queda actualizar la etiqueta.
37 Coge el evento ListPicker_ciudades.AfterPicking
38 Coge un bloque "set etiqueta_ciudad.Text" y ponlo dentro.
39 Finalmente coge un bloque ListPicker_ciudades.Selection que contendrá el nombre de la ciudad elegida. Tu programa tiene que quedar así: