2010-10-21 3 views
2

J'ai un ListView que je suis en train de remplir avec des ficelles en ce moment. Il contient actuellement 10 éléments, mais la vue elle-même est seulement assez grande pour afficher 5. Donc la liste doit bien sûr défiler. Je l'ai construit la liste en utilisant le code suivant:Android: ListView personnalisé OnItemClickListener Weird questions

ListView:

<RelativeLayout 
    android:id="@+id/catList" 
    android:layout_width="wrap_content" 
    android:layout_height="216dip" 
    android:layout_marginTop="120dip" 
    > 
    <ListView 
     android:id="@+id/categoryList" 
     android:layout_width="308dip" 
     android:layout_height="216dip" 
     android:layout_marginLeft="6dip" 
     android:background="#ffffff" 
     android:divider="#ffffff" 
     android:choiceMode="singleChoice" 
     android:cacheColorHint="#00000000" 

     > 
    </ListView> 
    <ImageView 
     android:id="@+id/catListFrame" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"  
     android:layout_alignParentTop="true" 
     android:src="@drawable/selectorframe" 
     /> 
</RelativeLayout> 

Donc, fondamentalement, il y a un cadre d'image autour de la liste. Tout est imbriqué dans une autre mise en page.

Je dispose d'un fichier xml d'élément personnalisé et qui ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" 
    android:padding="10dip" 
    android:background="#ffffff" 
    > 
    <TextView 
     android:id="@+id/catTitle" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:textSize="20dip" 
     android:textColor="#000000" 
    > 
    </TextView> 
</LinearLayout> 

Voici le java qui fait tout le travail:

private void setCategoryControls(){ 
    btnBackHome = (ImageView)findViewById(R.id.catHomeBtn); 
    btnBackHome.setOnClickListener(goHome); 
    catList = (ListView)findViewById(R.id.categoryList); 
    catList.setOnItemClickListener(selectCat); 
    demoCats = new ArrayList<String>(); 
    for(int i=1;i<=10;i++){ 
     demoCats.add("Item " + i); 
    } 
    m_catAdapter = new CatAdapter(this,R.layout.catitem,demoCats); 
    catList.setAdapter(m_catAdapter); 

} 

private OnItemClickListener selectCat = new OnItemClickListener(){ 
    public void onItemClick(AdapterView<?> a, View v, int position, long id){ 
     if(selCatView!=null){ 
      selCatView.setBackgroundColor(Color.parseColor("#ffffff")); 
     } 
     v.setBackgroundColor(Color.parseColor("#ffaa00")); 
     selCatView = v; 
    } 
}; 
private class CatAdapter extends ArrayAdapter<String>{ 

    private ArrayList<String> items; 

    public CatAdapter(Context context, int textViewResourceId, ArrayList<String> items){ 
     super(context, textViewResourceId, items); 
     this.items = items; 
    } 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
      View v = convertView; 
      if (v == null) { 
       LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
       v = vi.inflate(R.layout.catitem, null); 
      } 
      String cat = items.get(position); 
      if (cat != null) { 
        TextView catName = (TextView) v.findViewById(R.id.catTitle); 
        if (catName != null) { 
          catName.setText(cat); 
        } 

      } 
      return v; 
    } 
} 

Qu'est-ce qui se passe est lorsque je clique sur un élément la liste devrait simplement changer la couleur d'arrière-plan de cet article, à la place elle met généralement en évidence 2 éléments (un qui est visible et un que je dois faire défiler), et la plupart du temps ce n'est même pas le bon élément. Aussi, si je défile pendant qu'un élément est en surbrillance, il changera aléatoirement autour de ce qui est surligné lorsque je fais défiler l'élément en surbrillance sur et hors de l'écran. Si je devais deviner, je dirais que c'est lié au fait que ListView ne fait apparemment que suivre les enfants visibles. Même s'il a un adaptateur avec 10 éléments, si je lance un getChildCount dans la liste, il ne montre que 5 ou 6 selon que l'on est partiellement visible ou non, mais il ne montre jamais plus ou moins que le nombre d'éléments visibles.

Répondre

0

En effet, ListView conserve uniquement la trace des enfants actuellement affichés. C'est pourquoi vous recyclez les vues dans votre méthode getView.

La manière la plus simple de réaliser ce que vous essayez d'obtenir est de donner à vos vues une liste d'états pouvant être dessinée comme arrière-plan. Faire une liste d'état XML dessinable avec un state_pressed et un état par défaut (et éventuellement un state_focused) et mettez cela comme le drawable d'arrière-plan de votre catitem. Bien sûr, vous devez également supprimer le code qui le fait à la main =)

Plus de documentation sur la liste d'état drawables dans here et here.

+0

Merci, je vais essayer. Ma seule préoccupation est que j'aurai éventuellement besoin de déclencher un événement qui prend des informations à partir de l'élément cliqué. S'il enregistre toujours le mauvais article, il va bousiller les choses. – LoneWolfPR

+0

@LoneWolfPR - Ne vous inquiétez pas, vous n'aurez pas ce problème. Qu'est-ce qui se passe dans votre exemple n'est pas le clic obtenir le mauvais élément: c'est le drawable utilisé par différents éléments partagés. Depuis que vous faites défiler, vous utilisez la même vue, il utilise toujours l'arrière-plan d'une vue sur laquelle vous avez cliqué. Mais vous obtenez vraiment l'élément de liste correct à chaque fois. – Jean

Questions connexes