Cómo obtener elementos seleccionados de la vista de lista de selección múltiple

Estoy usando un adaptador de matriz y estoy agregando una lista de cadenas de caracteres, la lista es de selección múltiple, ¿cómo puedo hacer clic en los valores de los elementos de la lista?

my_contacts_list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice,conts_list); my_contacts_list.setAdapter(adapter); 

Estaba tratando de hacer esto,

 SparseBooleanArray positions = my_contacts_list.getCheckedItemPositions(); int size=positions.size(); int i=0; while(i <= size){ conts_list.get(positions.get(i)); i++; } 

Pero position.get (i) es una lista de arreglos, ¿cómo recuperar los elementos seleccionados?

SparseBooleanArray.get devuelve un valor booleano, pero creo que debe verificarlo para cada posición en su lista, por ejemplo

 int len = listView.getCount(); SparseBooleanArray checked = listView.getCheckedItemPositions(); for (int i = 0; i < len; i++) if (checked.get(i)) { String item = cont_list.get(i); /* do whatever you want with the checked item */ } 

Esta API es un desastre. Esto es lo que funciona para mí.

 SparseBooleanArray checked = tags.getCheckedItemPositions(); for (int i = 0; i < checked.size(); i++) { if(checked.valueAt(i)) { Tag tag = (Tag) tags.getItemAtPosition(checked.keyAt(i)); Log.i("xxxx", i + " " + tag); } } 

Creo que la manera más rápida de obtener la información de este SparseArray es iterar sobre las claves (de hecho, estoy bastante seguro de que las soluciones anteriores no funcionarán en todos los casos). ListView ingresará un par (índice, verdadero) en SparseBooleanArray para cada índice seleccionado.

Entonces el código podría verse así:

 SparseBooleanArray checked = lv.getCheckedItemPositions(); int size = checked.size(); // number of name-value pairs in the array for (int i = 0; i < size; i++) { int key = checked.keyAt(i); boolean value = checked.get(key); if (value) doSomethingWithSelectedIndex(key); } 

Creo que la respuesta de Daren Robbins es incorrecta, aquí está mi respuesta:

 ArrayList ids = extras.getStringArrayList("commonids"); SparseBooleanArray checked = lv.getCheckedItemPositions(); for (int i = 0; i < checked.size(); i++) { if(checked.get(i)) Log.i("CheckedItem", ids.get(checked.indexOfKey(i))); } 

Asumir ids es una lista de arrays con el mismo tamaño de la vista de lista que contiene los identificadores de los elementos en la vista de lista

Lo que pasa es que debe iterar todos los elementos de la vista de lista pero no las posiciones marcadas.

Definir las variables:

  • listView (La instancia de tu ListView)
  • nombres (el ArrayList que eres)
  • saveCheckedName (guarde todo el nombre marcado en este Arraylist)

      SparseBooleanArray checkedPositions = listView.getCheckedItemPositions(); for (int i = 0; i < subjectListView.getCount(); i++) { if (checkedPositions.get(i) == true) { saveCheckedName.add(names.get(i)); } } 

Como muchas otras cosas, los ListView s de selección múltiple son un problema real en Android.

En lugar de simplemente solicitar los elementos seleccionados como una List de Object s (querido Google, esto es lo que esperamos):

 List selected_items = my_list_view.getSelectedItems(); 

estamos obligados a usar esta API estupendamente ridícula:

 SparseBooleanArray checked = my_list_view.getCheckedItemPositions(); int num_selected = 0; for(int i = 0; i < checked.size(); i++) { if(checked.valueAt(i)) { num_selected++; int key = checked.keyAt(i); boolean value = checked.get(key); if (value) { // } } } 

El horriblemente llamado SparseBooleanArray se completa llamando a getCheckedItemPositions() aún más horrible, en ListView . Pero en lugar de devolver las posiciones de cada elemento seleccionado / verificado en la lista, devuelve la posición de cada elemento de la lista que SIEMPRE se ha tocado, ¡ya sea que esté actualmente seleccionado o no! Increíble, pero cierto.

Para calcular si el elemento se está ACTUALMENTE ACTUAL verificado, nos vemos obligados a probar valueAt(i) busca de veracidad mientras valueAt(i) la matriz de elementos "se tocó alguna vez".

Además de esta locura, si queremos calcular el número de elementos seleccionados, parece que nos vemos obligados a incrementar nuestro propio contador (por ejemplo, num_selected ).

Con API como esta, ¡no es de extrañar que los desarrolladores estén enojados!

CÓMO SOLUCIONÉ EL PROBLEMA con una segunda ArrayList:

  1. Creó una segunda instancia de ArrayList
  2. Se actualizó esa instancia de ArrayList con los elementos DESEMBOLSADOS
  3. lo agregué a mi listadapter

     public void removeSelectedItems(){ updatedList = new ArrayList(); //initialize the second ArrayList int count = lv.getCount(); //number of my ListView items SparseBooleanArray checkedItemPositions = getListView().getCheckedItemPositions(); for (int i=0;i < count;i++){ if(!checkedItemPositions.get(i)) updatedList.add(liveNames.get(i)); //liveNames is the current ArrayList Log.e("TEST", liveNames.get(i)); } adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_multiple_choice, updatedList); setListAdapter(adapter);} 

Espero que sea útil 🙂

 Foo objectAtCheckedRow = null; for (int i = 0; i < positions.size(); i++) { //positions.size() == 2 objectAtCheckedRow = adapter.getItem(positions.keyAt(i)); //Do something significant with object here } 

Un par de cosas para entender

  • Es una lista de pares clave-valor.
  • La clave es el índice de una fila, obténgalo con positions.keyAt (i)
  • El valor es si la fila en ese índice está marcada o no (verdadera o falsa), obténgalo con positions.valueAt (i)
  • positions.get (i) devuelve el mismo valor booleano que .valueAt (i)
  • Cuidado con no mezclar los índices. No necesita ( y no debe ) iterar sobre toda su lista. Use int i para repetir las posiciones, pero no use i para obtener objetos de su lista
  • Pero en este caso específico (listView.getCheckedPositions ()) solo rellena en verdadero (filas marcadas), por lo que en realidad no necesita verificar el uso de .get (i) ni .valueAt (i)

Ejemplo: Supongamos que ha marcado los elementos quinto y octavo de la lista (índice 4 y 7), luego position.size () == 2 y yo seré 0 y luego 1

Así que cuando:

i == 0 luego keyAt (i) == 4

i == 1 luego keyAt (i) == 7

i == 0 OR i == 1 luego valueAt (i) == true AND get (i) == true

FYI, así es como lo hizo Google:

Extraído de http://mytracks.googlecode.com/hg/MyTracks/src/com/google/android/apps/mytracks/util/Api11Adapter.java

 /** * Gets the checked positions in a list view. * * @param list the list view */ private int[] getCheckedPositions(ListView list) { SparseBooleanArray positions = list.getCheckedItemPositions(); ArrayList arrayList = new ArrayList(); for (int i = 0; i < positions.size(); i++) { int key = positions.keyAt(i); if (positions.valueAt(i)) { arrayList.add(key); } } int[] result = new int[arrayList.size()]; for (int i = 0; i < arrayList.size(); i++) { result[i] = arrayList.get(i); } return result; } 

y aquí está mi versión adaptada:

 public static List getAbsListViewCheckedItemPositions(AbsListView absListView) { SparseBooleanArray checked = absListView.getCheckedItemPositions(); List positions = new ArrayList<>(); int checkedSize = checked.size(); for (int i = 0; i < checkedSize; i++) { if (checked.valueAt(i)) { positions.add(checked.keyAt(i)); } } return positions; } 

Usamos esto en nuestra clase de utilidad Android. Los generics ayudan a evitar las advertencias del comstackdor, pero puede eliminarlos si su adaptador devuelve varios tipos.

 public static  Collection getCheckedItems(ListView listView) { Collection ret = new ArrayList(); SparseBooleanArray checkedItemPositions = listView.getCheckedItemPositions(); for (int i = 0; i < checkedItemPositions.size(); i++) { if (checkedItemPositions.valueAt(i)) { T item = (T) listView.getAdapter().getItem(checkedItemPositions.keyAt(i)); ret.add(item); } } return ret; } 

Muy simple, use el código debajo

 listViewRequests.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView adapterView, View view, int i, long l) { AppCompatCheckedTextView checkBox = (AppCompatCheckedTextView) view; if (checkBox.isChecked() == true){ Log.i("CHECK",checkBox.isChecked()+""+checkBox.getText().toString()); } } }); 

Creo que otra opción es simplemente hacer un seguimiento de todo esto usted mismo.

  list.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView listView, View selectedItem, int position, long itemId) { //Keep a reference here, and toggle a global variable.