web-dev-qa-db-fra.com

Comment obtenir les éléments sélectionnés à partir de la vue Liste de sélection multiple

J'utilise un adaptateur de tableau et j'ajoute à cela une liste de tableaux de chaînes, la liste est multi-sélection, comment puis-je obtenir les valeurs des éléments de liste cliqués?

my_contacts_list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
ArrayAdapter<String> adapter=new ArrayAdapter<String>(this, Android.R.layout.simple_list_item_multiple_choice,conts_list);
  my_contacts_list.setAdapter(adapter);

J'essayais de faire ça,

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

Mais position.get (i) est une liste de tableaux, comment récupérer alors les éléments sélectionnés?

46
preethi

SparseBooleanArray.get renvoie un booléen, mais je pense que vous devez le vérifier pour chaque position dans votre liste, par exemple.

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 */
 }
43
Daren Robbins

Cette API est un gâchis. Voici ce qui fonctionne pour moi.

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);
    }
}
43
Roger Keays

Je crois que le moyen le plus rapide pour obtenir les informations de ce SparseArray est d'itérer sur les clés (en fait, je suis assez sûr que les solutions ci-dessus ne fonctionneront pas dans tous les cas). ListView entrera une paire (index, true) dans SparseBooleanArray pour chaque index sélectionné.

Le code pourrait donc ressembler à ceci:

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);
}
17
Karl

Je pense que la réponse de Daren Robbins est erronée, voici ma réponse:

ArrayList<String> 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)));
}

Supposons que ids est une liste d'arrayl avec la même taille que la vue de liste contenant les identifiants des éléments dans la vue de liste

4
Shereef Marzouk

Comme tant d'autres choses, les ListViews à sélection multiple sont un vrai problème dans Android.

Au lieu de simplement demander les éléments sélectionnés en tant que List de Objects (cher Google, c'est ce que nous attendons):

List selected_items = my_list_view.getSelectedItems();

nous sommes obligés d'utiliser cette API incroyablement ridicule:

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) {
                //
            }
        }
    }

La SparseBooleanArray horriblement nommée est remplie en appelant la _ encore plus horriblement nommée getCheckedItemPositions() sur la ListView. Mais au lieu de renvoyer les positions de chaque élément sélectionné/vérifié dans la liste, il renvoie la position de chaque élément de la liste qui A ÉTÉ JAMAIS touché, qu'il soit actuellement réellement sélectionné ou non! Incroyable, mais vrai.

Pour calculer si l'élément est ACTUELLEMENT ACTUELLEMENT vérifié, nous sommes obligés de tester valueAt(i) pour la véracité tout en parcourant le tableau des éléments "a été touché".

En plus de cette folie, si nous voulons calculer le nombre d'articles sélectionnés, nous semblons obligés d'incrémenter notre propre compteur (par exemple num_selected).

Avec des API comme celle-ci, il n'est pas étonnant que les développeurs soient énervés!

3
rmirabelle

Le fait est que vous devez itérer tous les éléments de la liste, mais pas les positions cochées.

Définissez les variables:

  • listView (L'instance de vous ListView)
  • noms (ArrayList que vous êtes)
  • saveCheckedName (enregistrez tous les noms cochés dans cette liste)

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

Pour info, voici comment Google l'a fait:

Extrait 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<Integer> arrayList = new ArrayList<Integer>();
    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;
}

et voici ma version adaptée:

public static List<Integer> getAbsListViewCheckedItemPositions(AbsListView absListView) {
    SparseBooleanArray checked  = absListView.getCheckedItemPositions();
    List<Integer> 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;
}
1
Hai Zhang

Nous l'utilisons dans notre classe d'utilitaires Android. Les génériques permettent d'éviter les avertissements du compilateur, mais vous pouvez les supprimer si votre adaptateur renvoie plusieurs types.

public static <T> Collection<T> getCheckedItems(ListView listView) {
        Collection<T> 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;
}
1
Steven Spungin

Je pense qu'une autre option est de garder une trace de tout cela vous-même.

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

COMMENT J'AI RÉSOLU LE PROBLÈME avec une deuxième ArrayList:

  1. Création d'une seconde instance ArrayList
  2. Mise à jour de cette instance ArrayList avec les éléments UNCHECKED
  3. l'a ajouté à l'adaptateur my listadapter

    public void removeSelectedItems(){
    
    updatedList = new ArrayList<String>(); //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<String>(this,
            Android.R.layout.simple_list_item_multiple_choice, updatedList);
    
    setListAdapter(adapter);}
    

J'espère que ce sera utile :)

1
ArloGrant

Très simple, utilisez le code ci-dessous

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());
                    }
                }
            });
1
Girish Kumar Shakya
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
}

Quelques choses à comprendre

  • Il s'agit d'une liste de paires clé-valeur.
  • Le clé est l'index d'une ligne, obtenez-le avec les positions.keyAt (i)
  • valeur est de savoir si la ligne à cet index est vérifiée ou non (vrai ou faux), obtenez-la avec les positions.valueAt (i)
  • positions.get (i) renvoie le même booléen comme .valueAt (i)
  • Attention à ne pas confondre les index. Vous ne pas devez (et ne devriez pas) parcourir toute votre liste. Utilisez int i pour parcourir les positions, mais n'utilisez pas i pour obtenir des objets de votre liste
  • Mais dans ce cas spécifique (listView.getCheckedPositions ()), il ne remplit que true (lignes cochées), vous n'avez donc pas besoin de vérifier en utilisant .get (i) ni .valueAt (i)

Exemple: disons que vous avez coché les 5e et 8e éléments de la liste (index 4 et 7), puis positions.size () == 2 et je serai 0 puis 1

Donc quand:

i == 0 puis keyAt (i) == 4

i == 1 puis keyAt (i) == 7

i == 0 OR i == 1 alors valueAt (i) == true ET get (i) == true

1
Kevin Worth