2008-11-02 10 views
101

J'ai besoin de connaître la position en pixels d'un élément dans une liste qui a été affichée en utilisant un ListView. Il semble que je devrais obtenir l'un des de TextView et puis utiliser getTop(), mais je ne peux pas comprendre comment obtenir une vue enfant d'un ListView.Android: Accéder aux vues enfant à partir d'un ListView

Mise à jour: Les enfants du ViewGroup ne correspondent pas 1 à 1 avec les éléments de la liste, pour un ListView. Au lieu de cela, les enfants de ViewGroup correspondent uniquement aux vues visibles en ce moment. Donc, getChildAt() fonctionne sur un index interne au ViewGroup et n'a pas nécessairement de rapport avec la position dans la liste utilisée par le ListView.

Répondre

210

Voir: Android ListView: get data index of visible item et se combiner avec une partie de la réponse de pieds au-dessus, peut vous donner quelque chose comme:

int wantedPosition = 10; // Whatever position you're looking for 
int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); // This is the same as child #0 
int wantedChild = wantedPosition - firstPosition; 
// Say, first visible position is 8, you want position 10, wantedChild will now be 2 
// So that means your view is child #2 in the ViewGroup: 
if (wantedChild < 0 || wantedChild >= listView.getChildCount()) { 
    Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen."); 
    return; 
} 
// Could also check if wantedPosition is between listView.getFirstVisiblePosition() and listView.getLastVisiblePosition() instead. 
View wantedView = listView.getChildAt(wantedChild); 

L'avantage est que vous n'êtes pas itérez les enfants du ListView, ce qui pourrait prendre un coup de performance .

+10

Grande réponse, mais ne fonctionne pas tout à fait correctement lorsque vous avez des vues d'en-tête dans votre liste. L'affectation à 'firstPosition' devrait être' int firstPosition = listView.getFirstVisiblePosition() - listView.getHeaderViewsCount(); 'pour corriger cela. – pospi

+0

@pospi: merci, bon point! J'ai mis à jour ma réponse pour tenir compte de cela. – Joe

+33

Êtes-vous un médecin? parce que vous êtes un épargnant de vie. –

5

Une recherche rapide des docs pour la classe ListView a révélé des méthodes getChildCount() et getChildAt() héritées de ViewGroup. Pouvez-vous les parcourir en les utilisant? Je ne suis pas sûr mais ça vaut le coup d'essayer.

Je l'ai trouvé here

+1

Je l'ai essayé, pour faire des sélections. Cela fonctionne habituellement mais il y a parfois des erreurs au hasard et ce n'est pas fiable. Je ne le recommanderais pas. – Timmmm

+0

Merci Timmmm, je ne l'avais pas vraiment essayé juste trouvé dans les docs. – Feet

-9

Cela suppose que vous connaissez la position de l'élément dans le ListView:

View element = listView.getListAdapter().getView(position, null, null); 

alors vous devriez être en mesure d'appeler à déterminer les éléments getLeft() et GetTop() position de l'écran.

+42

'getView()' est appelé en interne par ListView, lors du remplissage de la liste. Vous * ne devriez pas l'utiliser pour obtenir la vue à cette position dans la liste, en appelant 'getView()' avec null pour le 'convertView' provoque l'adaptateur pour gonfler une nouvelle vue de la ressource de mise en page de l'adaptateur (n'obtient pas le vue qui est déjà affichée). – Joe

+2

Excellent point! – jasonhudgins

+1

La position paire correspond à une position dans l'écran visuel et non à la position de la source de données de l'adaptateur. – Vikas

15

Ce code est plus facile à utiliser:

View rowView = listView.getChildAt(viewIndex);//The item number in the List View 
    if(rowView != null) 
     { 
      // Your code here 
     } 
+0

Cela fonctionne bien. Je ne sais pas pourquoi vous avez une downvote ... upvote! – Mark

+9

ne fonctionne pas toujours. getChildAt compte à partir de la première ligne visible et non du haut des données. – SteelBytes

+13

L'argument ViewID est confus. C'est un index (ou une position). L'ID de vue est un nombre entier arbitraire généré par l'outil aapt. –

5
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

    @Override 
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) 
{  
    View v; 
    int count = parent.getChildCount(); 
    v =parent.getChildAt(position); 
    parent.requestChildFocus(v, view); v.setBackground(res.getDrawable(R.drawable.transparent_button)); 
      for (int i=0; i<count; i++) 
      { 
       if (i!= position) 
       { 
        v = parent.getChildAt(i);t v.setBackground(res.getDrawable(R.drawable.not_clicked)); 

       } 
      } 
     } 
    }); 

Fondamentalement, créer deux dessinables - qui est transparente, et une autre qui est la couleur souhaitée. Demande le focus à la position cliquée (position int telle que définie) et change la couleur de cette ligne. Parcourez ensuite le parent listview et modifiez toutes les autres lignes en conséquence. Cela tient compte du fait qu'un utilisateur clique plusieurs fois sur le listview. Ceci est fait avec une mise en page personnalisée pour chaque ligne dans le listview. (Très simple, il suffit d'un nouveau fichier de mise en page avec un textview - ne contiendraient pas focusable ou cliquable) Aucun adaptateur personnalisé requis - Adaptateur réseau d'utilisation

+0

getChildAt est relatif aux éléments en cours de défilement. Cela va cesser de fonctionner si vous faites défiler votre liste un peu. – nurettin

4
int position = 0; 
listview.setItemChecked(position, true); 
View wantedView = adapter.getView(position, null, listview); 
+1

Elaborer un peu – innoSPG

+0

Dieu vous bénisse mec, vous sauvez ma vie. – Euphor08

Questions connexes