Desarrollando Android #5
Hoy vamos a tocar las listas. Antes de nada, muchísimas gracias a los artículos de Android Developers, Proyectosimio y de SGOliver que me han servido de inestimable ayuda.
Puedes seguir anteriores artículos de esta sección aquí
Dividiendo la pantalla en dos
Bien, pues el siguiente paso para mejorar la aplicación es tener la lista de parkings también en un formato de lista para acceder rápidamente a los párkings. Lo ideal será dividir la pantalla en dos, por un lado dichos párkings en formato lista y por el otro en formato mapa.
Para ello vamos a tocar el layout. En res -> layout -> activity_main.xml vamos a cambiar lo que teníamos por lo siguiente.
Si nos fijamos, primero creamos un LinearLayout con un identificador @+id/top_half que va a rellenar todo. En el interior de este primer LinearLayout añadimos un ListView, lugar donde insertaremos nuestra lista. A continuación, en el siguiente LinearLayout insertamos el mapa tal y como lo teníamos hasta ahora.
Para conseguir que la pantalla se divida exactamente por la mitad utilizamos los weights (o pesos). Al poner la propiedad android:layout_weight=»1″ en ambos LinearLayout le estamos indicando que ambos tienen la misma importancia en la app, y por tanto, le da la mitad de espacio a cada uno. Si quisieramos que el mapa ocupase más, indicaríamos un peso mayor, por ejemplo «2». La regla que se sigue para distribuir el espacio es la siguiente:
Espacio que ocuparé = Peso / Suma de todos los pesos
Por ejemplo: Un linearlayout con peso 3 y otro con 1, ocuparán respectivamente: 3 / (3+1) = 75% y 1/ (3+1) = 25%. Si queréis más información sobre el tema os recomiendo este artículo y este otro.
Añadiendo la Lista
Diseño
Lo primero que hemos de hacer es definir correctamente el contenedor de esta lista en los layouts. ¿Pero eso no lo habíamos hecho ya? No. Para que lo entendamos, antes hemos divido en dos la pantalla diciendo que arriba vendría una lista. Ahora estamos definiendo el estilo de cada fila: su altura, espacios, los colores, el texto, etc..
Aquí me tiré varias horas para dar con el estilo que me gustase. Ya os aviso que es un infierno y es recomendable repasar las propiedades wrap_content y demás de los layout_width (aquí, aquí y aquí) y los pesos de los que hemos hablado. Básicamente, este diseño mío crea una lista en la que cada fila está compuesta de el Nombre del parking con el id LblTitle y un texto más pequeño indicando si está libre o no con el id LblStatus. Estos ids los utilizaremos más tarde y pueden tener el nombre que queráis..
Adapter
A continuación necesitamos un adapter (adaptador). ¿Por qué? Pues bien, nosotros tenemos una lista, sí. Pero, ¿de qué? Pues bien, se lo hemos de decir a Android, y eso lo haremos a través de este adapter. Para ello, en nuestra clase principal creamos una nueva clase que extiende el ArrayAdapter
Antes de nada, definimos el constructor por defecto que está compuesto de una Activity context y una lista de los objetos que recibimos, en mi caso los ParkingMarker. Y a continuación la clase que nos interesa: getView.
En getView vamos a definir los tipos de contenido que queremos que aparezca en nuestra lista y dónde queremos que estén. Así pues, lo primero que hacemos es definir un item de esta lista y le asignamos el diseño que hemos hecho antes con las dos primeras líneas.
A continuación, definimos los elementos de nuestro item:
- asociamos al TextView lblTit (nombre inventado) el item del layouts.list_details.xml LblTitle que hemos definido en la etapa de diseño.
- asociamos al TextView lblStat del mismo modo el item LblStatus.
- además, miramos si el parking obtenido está libre o no, y en función le ponemos el color verde o rojo.
- finalmente retornamos este item que hemos creado.
Añadiendo el código
Para implementar la lista, haremos lo siguiente.
1. Crearemos tres variables: lstOptions, adapter y parkings_data privadas a nivel de clase para que se puedan acceder desde cualquier subclase. La variable parkings ya existía de la entrega anterior.
private ListView lstOptions;
private List parkings;
List parkings_data ;
ParkingAdapter adapter;
2. En el onCreate
//Creamos la lista de párkings
parkings = new ArrayList();
//Añadimos nuestros parkings a la lista
parkings_data = new ArrayList();
parkings_data = parkings;
adapter = new ParkingAdapter(MainActivity.this,parkings_data);
lstOptions = (ListView)findViewById(R.id.LstParkings);
lstOptions.setAdapter(adapter);
Esperando un tiempo
Y ahora viene una cuestión que hemos de tener en cuenta. Es importante fijarse que el parkings_data recoge la información de la variable parkings. Esta variable es la que tenemos compartida con los mapas que al parsear el archivos XML ha generado.
Así pues, si queremos asignárselo hemos de asegurarnos que la variable parkings esté llena. Pero como ésta se llena de forma asíncrona, hay que ir con cuidado: hemos de asegurarnos que la tarea de la clase asíncrona se ha acabado antes de llamar al adapter. Eso lo haremos utilizando el método get() de nuestra clase asíncrona. Después de la línea
task.execute(URL);
Introduciremos el siguiente código
try {
task.get(2500, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Y ya está, ya tenemos nuestra lista de parkings en la mitad superior de nuestra página cargándose correctamente.
En la próxima entrega veremos como añadir la barra superior que vemos en la captura y cómo añadir listeners!
Os recuerdo que el código fuente del proyecto se encuentra en GitHub
¡Cualquier duda, sugerencia o cuestión me podéis encontrar en twitter!