68 votes

ListView getChildAt retournant null pour les enfants visibles

J'obtiens un comportement étrange de la part d'un listview et de la méthode getChildAt.

J'ai un HashSet, iconsToUpdate, d'icônes qui ont été modifiées dans la base de données. Je veux itérer sur les lignes visibles pour voir si l'une de leurs icônes doit être mise à jour pour refléter les nouvelles icônes. Je n'ai pas besoin de tester les icônes qui ne sont pas actuellement visibles car elles seront dessinées correctement lors du rendu.

Mon problème est que getChildAt renvoie null alors qu'il ne devrait pas. Je sais que getChildAt ne peut renvoyer que les vues qui sont actuellement visibles, mais il renvoie un résultat nul pour certaines des lignes visibles.

Voici mon code qui itère sur les lignes visibles :

Logger.debug("First visible index: " + f_listView.getFirstVisiblePosition());
Logger.debug("Last visible index: " + f_listView.getLastVisiblePosition());
for (int i = f_listView.getFirstVisiblePosition(); i <= f_listView.getLastVisiblePosition(); i++) {
    String tag = "asdf"; // Remove when bug is fixed.
    if (f_listView == null) {
        Logger.debug("f_listView is null");
    } else if (f_listView.getChildAt(i) == null) {
        Logger.debug("Child at index " + i + " is null");
    } else {
        tag = (String) f_listView.getChildAt(i).getTag();
        Logger.debug("Successful at index " + i + ", tag is: " + tag);
    }
    if (iconsToUpdate.contains(tag)) {
        setIcon(i, f_aim.getInHouseIcon(tag));
    }
}

Voici le journal correspondant à une exécution de cette boucle :

D/...: First visible index: 3
D/...: Last visible index: 8
D/...: Successful at index 3, tag is: ...
D/...: Successful at index 4, tag is: ...
D/...: Successful at index 5, tag is: ...
D/...: Child at index 6 is null
D/...: Child at index 7 is null
D/...: Child at index 8 is null

Il convient de noter que le premier et le dernier index visibles sont correctement signalés, car je visualise les lignes 3 à 8 lorsque je lance cette opération. Les lignes 6, 7 et 8 sont affichées correctement. Comment sont-elles affichées si elles sont nulles ?

Par ailleurs, je ne sais pas si c'est important, mais la ligne 5 est la dernière ligne visible lorsque je suis en haut de la liste.

Toute information sur la raison pour laquelle ces lignes sont retournées comme étant nulles serait grandement appréciée.

Merci !

135voto

C Nick Points 1088

ListView.getChildAt(i) fonctionne où 0 est la toute première ligne visible et (n-1) est la dernière ligne visible (où n est le nombre de vues visibles).

Le get last/first visible renvoie la position dans le dataAdapter que vous avez. Donc, puisque vous commencez à la position 3, avec ce qui semble être 6 vues visibles, c'est quand vous obtenez pour les positions 6-8 vous obtenez null.

Dans votre exemple, getChildAt(0) renverrait la position 3. Ce que je fais habituellement, c'est de stocker la position dans mes vues pour pouvoir la consulter plus tard dans mon DataAdapter si j'ai besoin de valeurs.

Je pense que votre boucle for devrait ressembler à ça :

for (int i = 0; i <= f_listView.getLastVisiblePosition() - f_listView.getFirstVisiblePosition(); i++) 

J'espère que cela vous aidera.

0 votes

Cool, content de pouvoir aider. Acceptez aussi si vous le pouvez, j'adore recevoir des points :)

67 votes

Aha ! Merci. Il serait utile que la documentation précise que getChildAt(i) utilise la position VISIBLE au lieu de la position logique. Cela m'aurait évité de perdre quelques cheveux.

3 votes

Exactement, cela n'est pas décrit dans la documentation. @CNick : des références à ce sujet ?

3voto

A. Abiri Points 4376

Lorsque vous appelez listView1.getLastVisiblePosition() y listView1.getFirstVisiblePosition() El listview renvoie les positions des éléments qui sont partiellement visibles dans le listview. Par exemple, le premier élément peut être à moitié visible et le dernier élément peut être à moitié visible. Dans ce cas, même si vous pouvez voir une partie de l'élément dans le listview, l'adaptateur n'a pas encore appelé la fonction getView() pour l'élément et donc l'élément est toujours considéré comme nul.

0 votes

Quelqu'un peut-il confirmer si cela est vrai ?

0voto

Nikola Despotoski Points 13670

Elles sont peut-être partiellement visibles. Mais lorsque la fonction getView() essaie de recycler les vues, elle récupère les vues COMPLÈTEMENT visibles, tandis que les autres sont considérées comme nulles. Par exemple, si vous faites défiler la liste et que l'élément supérieur est partiellement visible et que l'élément inférieur est partiellement visible, ces éléments sont nuls mais vous les voyez quand même.

0 votes

Hmmm, bien, toutes les rangées 3-8 sont complètement visibles. Je ne pourrais pas avoir trois rangées consécutives partiellement visibles, donc je pense qu'il y a quelque chose de plus qui se passe ici. Merci quand même pour la réponse !

0 votes

Essayez de commencer à partir de i=0 ? et vérifiez le résultat.

0voto

Anju Dahiya Points 11

J'ai essayé par tous les moyens dans OnListItemClickListener(), mais sans succès. Finalement, j'ai fait quelques modifications dans mon adaptateur personnalisé pour listview. Ici, dans getView(), j'applique le clickListener sur l'élément que j'ai ajouté dans la liste fréquemment. et faire toutes les fonctionnalités requises là. Voici mon code, où j'ajoute une vue d'image dans la liste et où j'applique le listener sur la vue d'image.

Je pense que cela aidera ceux qui veulent changer la couleur lorsqu'un élément de liste spécifique est >sélectionné. Allez-y

Dans getView() de l'adaptateur personnalisé //---------------------------------code------------------------------------------

LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

`View rowView = inflater.inflate(R.layout.icon_image_layout, parent, false); ImageView imageView = (ImageView) rowView.findViewById(R.id.Icon_ImageView); imageView.setClickable(true); final int pos=position; imageView.setOnTouchListener(new View.OnTouchListener() {

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub

        // TODO Auto-generated method stub
        try{
        if(previous_view!=null)
            previous_view.setBackgroundColor(Color.WHITE);
        }catch (Exception e) {
            System.out.println("Exception Occurs Previous View");
        }
        v.setBackgroundColor(Color.RED);
        MainActivity.imageView.setImageResource(MainActivity.Image_Name[pos]);
        previous_view=v;

        return false;
    }
});`

-2voto

citizen conn Points 8905

N'est-ce pas parce que vous dites

f_listView.getChildAt(i) 

Et vous devriez récupérer l'objet à cette position ?

f_listView.getItemAtPosition(i)

1 votes

Je ne pense pas. Je pense que getItemAtPosition récupère les données de cette ligne (de l'adaptateur), pas de la vue.

0 votes

Oui, Steelbytes. Dans le cas de CursorAdapter, il renvoie le curseur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X