Cuando en Android tenemos una lista de elementos en los que se pueden hacer varias selecciones simultáneas, el sistema emplea un objeto SparseBooleanArray para mapear los índices de los elementos seleccionados. El detalle está en que no sólo aparecen en el array los elementos seleccionados si no que Android crea un Array de una dimensión determinada y en ella aparecen elementos seleccionados y deseleccionados.

Básicamente el SparseBoolealArray está constituido por 3 elementos interesantes:

  1. un elemento mSize que nos indica el número de elementos a comprobar (no quiere decir que estén seleccionados),
  2. un elemento mKeys que mapea el índice de los elementos que o bien se encuentran seleccionados actualmente o están deseleccionados pero antes estuvieron seleccionados (sí, menudo lío) y, finalmente,
  3. un elemento mValues que mapea el índice mKey contra un booleano para indicar si, efectivamente, ese elemento de la lista está seleccionado o no.

Veamos un ejemplo sencillo: Una lista de 6 elementos. Vamos a ir viendo lo que hace Android cuando voy seleccionado y deseleccionando elementos.

1. Selecciono sólo un elemento de la lista, el tercero por ejemplo. El SparseBooleanArray quedará como sigue:

SparseBoolenArray seleccionado un elemento

ya véis. Al sistema le ha dado por crear 19 elementos en uno de los arrays. Cómo se mapea? Observad que mSize es 1 porque sólo hemos seleccionado un elemento. Ese elemento estará guardado en la posición 0 del array de mKeys (el elemento 2, o sea el 3 de la lista) y finalmente, en el mismo índice 0 en mValues podemos comprobar si efectivamente está seleccionado o no (en este caso sí, es true).

2. Voy a seleccionar ahora dos elementos, el 2 y el 5:

SBA_1

de nuevo la relación es similar a la anterior.

3. Ahora llega el detalle, voy a seleccionar el 2 y 5 y los voy a dejar seleccionados pero también voy a seleccionar el 1 y 4 pero los voy a deseleccionar después de seleccionarlos:

SBA_2

y aquí está el detalle interesante, sólo tengo 2 temas seleccionados pero mSize es 4 porque guarda referencia de los seleccionados (2 y 5) y los que estuvieron seleccionados aunque ahora no lo estén (1 y 4). Ése índice de referencia se guarda en mKeys en sus cuatro primeras posiciones y en estas mismas primeras cuatro posiciones podemos comprobar cuáles de los temas que guarda el array están efectivamente seleccionados (1 y 3 es true, o sea, de mKeys 1 y 3 equivalen a 1 y 4 que son los temas 2 y 5, recordad que los arrays empiezan siempre por el índice 0).

Así que, cómo leer el SparseBooleanArray para buscar los temas que ha seleccionado el usuario?? Yo uso este código, los habrá mejores y peores pero a mi me funciona y por eso os lo comparto:


SparseBooleanArray checked = listView.getCheckedItemPositions();

for (int i = 0; i < checked.size(); i++) {
if (checked.valueAt(i)) {
elementoSeleccionado = adapter.getItem(checked.keyAt(i));
}
}

Happy coding.

Anuncios