2010-04-16 9 views
34

J'ai vu l'exemple com.example.android.apis.view.List11 de ApiDemos. Dans cet exemple, chaque ligne prend la vue android.R.simple_list_item_multiple_choice. Chacune de ces vues a un TextView et un CheckBox.Liste à choix multiples avec vue personnalisée?

Maintenant, je veux chaque vue d'avoir 2 TextView s et 1 CheckBox, un peu similaire à la List3 exemple. J'ai essayé de créer un fichier mise en page personnalisée row.xml comme ceci:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <CheckBox 
     android:id="@+id/checkbox" 
     android:layout_alignParentRight="true" 
     android:layout_width="wrap_content" 
     android:layout_height="fill_parent" /> 
    <TextView 
     android:id="@+id/text_name" 
     android:textSize="13px" 
     android:textStyle="bold" 
     android:layout_toLeftOf="@id/checkbox" 
     android:layout_alignParentLeft="true" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
    <TextView 
     android:id="@+id/text_phone" 
     android:textSize="9px" 
     android:layout_toLeftOf="@id/checkbox" 
     android:layout_below="@id/text_name" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" /> 
</RelativeLayout> 

Puis, dans l » onCreate()Activity, je fais comme ceci:

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // Query the contacts 
    mCursor = getContentResolver().query(Phones.CONTENT_URI, null, null, null, null); 
    startManagingCursor(mCursor); 

    ListAdapter adapter = new SimpleCursorAdapter(this, 
      R.layout.row, 
      mCursor, 
      new String[] { Phones.NAME, Phones.NUMBER}, 
      new int[] { R.id.text_name, R.id.text_phone }); 
    setListAdapter(adapter); 
    getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
} 

Le résultat ressemble un peu à ce que je veux, mais il semble que la liste ne sache pas quel élément est sélectionné. Aussi, je dois cliquer exactement sur le CheckBox. Dans l'exemple List11, il suffit de cliquer sur la ligne de l'article.

Alors, que dois-je faire pour créer une liste à choix multiple avec ma vue personnalisée pour chaque rangée? Merci beaucoup.

+0

Avez-vous trouvé la réponse à celui-ci? un exemple peut-être? J'ai la même question :) http://stackoverflow.com/questions/3858501/multiple-choice-list-without-checkboxes-on-a-custom-view –

+1

Alors y avait-il une solution? Je suis coincé sur le même problème. – Pritam

Répondre

5

Chacune de ces vues possède un TextView et un CheckBox .

Non, ce n'est pas le cas. Il a un CheckedTextView.

Alors, que dois-je faire pour faire une liste de choix multiples avec mon point de vue personnalisée pour chaque ligne?

Essayez de faire la valeur CheckBoxandroid:id être "@android:id/text1" et voir si cela aide. C'est l'identifiant utilisé par Android pour le CheckedTextView dans simple_list_item_multiple_choice.

+1

Merci CommonsWare. J'ai juste essayé et ça n'a pas marché pour moi. Btw, où puis-je chercher l'implémentation de android.R.simple_list_item_multiple_choice? Je ne trouve pas le fichier xml avec ce nom dans ApiDemos. – Phil

+2

Ce n'est pas dans ApiDemos, c'est dans le SDK. Toutes les ressources SDK résident dans '$ ANDROID_SDK/plates-formes/$ VERSION/data/res', où' $ ANDROID_SDK' est où vous avez installé le SDK et '$ VERSION' est une version Android (par exemple,' android-2.1') . – CommonsWare

+1

Merci. J'ai vérifié le contenu de simple_list_item_multiple_choice. Ce que j'ai découvert est que cela fonctionne si la vue pour chaque ligne est juste . Une fois que je l'ai enveloppé avec une mise en page, les choses ne fonctionneront plus. Je ne sais pas comment entasser dans une autre vue pour afficher un autre texte. – Phil

1

Il est possible par une astuce

dans votre ListActivtyClass dans la méthode

protected void onListItemClick(ListView l, View v, int position, long id) { 
//just set 
<your_model>.setSelected(true); 
} 

maintenant vous personnalisés Adaptateur

public View getView(int position, View convertView, ViewGroup parent) { 
     if (convertView == null) { 
      LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = inflater.inflate(textViewResourceId, parent, false); 
     }  
     if (<your_model>.isSelected()) { 
      convertView.setBackgroundColor(Color.BLUE); 
     } else { 
      convertView.setBackgroundColor(Color.BLACK); 
     } 
     return convertView; 
    } 

cette façon, vous pouvez personnaliser l'affichage dans l'adaptateur lorsque l'élément est sélectionné dans la liste.

0

Vous avez la solution ... Vous pouvez obtenir les clics sur les vues (comme les cases à cocher dans les mises en page personnalisées) en ajoutant un écouteur à chacun d'eux dans l'adaptateur pendant que vous renvoyez la vue convertie dans getView(). Vous devrez peut-être passer une référence d'objet liste si vous avez l'intention d'obtenir des informations spécifiques à la liste. comme id de ligne.

7

La réponse de Rahul Garg est bonne pour la première fois que la liste est chargée, si vous voulez que certaines lignes soient vérifiées en fonction des données du modèle, mais après cela vous devez gérer les événements cocher/décocher vous-même.

Vous pouvez remplacer le onListItemCLick() du ListActivity pour cocher/décocher les lignes

@Override 
protected void onListItemClick(ListView l, View v, int position, long id) { 
    super.onListItemClick(l, v, position, id); 
    ViewGroup row = (ViewGroup)v; 
CheckBox check = (CheckBox) row.findViewById(R.id.checkbox);    
    check.toggle(); 
} 

Si vous le faites, ne réglez pas le ListView-CHOICE_MODE_MULTIPLE, car il fait des choses étranges lorsque vous appelez la fonction.

Pour récupérer la liste des lignes cochée, vous devez mettre en œuvre une méthode vous, appelant getCheckItemIds() sur le ListView ne fonctionne pas:

ListView l = getListView(); 
int count = l.getCount(); 
for(int i=0; i<count; ++i) { 
    ViewGroup row = (ViewGroup)l.getChildAt(i); 
    CheckBox check = (Checked) row.findViewById(R.id.ck1); 
    if(check.isChecked()) { 
     // do something 
    } 
} 
+0

Merci @JVitela :) Fonctionne pour moi –

0

Je veux confirmer que la réponse du Pritam est correcte. Vous avez besoin d'un onClickListener sur l'élément de chaque liste (définissez-le dans le getView() de l'adaptateur).

Vous pouvez créer un nouveau onClickListener() pour chaque article, ou implémenter l'adaptateur onClickListener() - dans ce cas, les articles doivent être étiquetés pour que l'auditeur sache sur quel article il opère. S'appuyer sur la liste onItemClickListener() - comme quelqu'un conseillé dans un autre thread - ne fonctionnera pas car le CheckBox interceptera l'événement click afin que la liste ne l'obtienne pas.

Et enfin @Rahul et JVitella:

La situation est que la CheckBox sur un élément de la liste doit être cliquable et checkable indépendamment de l'élément de la liste elle-même. Donc la solution est comme je viens de le décrire ci-dessus.

17

Vous devez faire votre propre RelativeLayout qui implémente l'interface Checkable et une référence au CheckBox ou au CheckedTextView (ou une liste si elle est en mode à choix multiples).

Regardez ce post: http://www.marvinlabs.com/2010/10/29/custom-listview-ability-check-items/

+1

Lien publié résout aussi des problèmes lorsque l'utilisateur clique directement sur la case – Rainbowbreeze

+3

Le tutoriel est bon, mais il manque une partie importante: comment pouvez-vous gérer les clics d'article dans l'activité qui détient le ListView pour que vous puissiez afficher une barre d'action contextuelle par exemple? – Konsumierer

+0

@ ferdy182 Le poste auquel vous faites référence n'est plus disponible. Pouvez-vous s'il vous plaît fournir une copie de l'article (ou du code au moins)? Merci –

1

exemple simple comment obtenir une mise en page personnalisée pour travailler comme case à cocher personnalisée:

private class FriendsAdapter extends ArrayAdapter<WordsterUser> { 
    private Context context; 

    public FriendsAdapter(Context context) { 
     super(context, R.layout.listitem_oneline); 

     this.context = context; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     final int pos = position; 

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

     View rv = inflater.inflate(R.layout.listitem_oneline, parent, false); 
     rv.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       boolean checked = friendsListView.isItemChecked(pos); 
       friendsListView.setItemChecked(pos, !checked); 
      } 
     }); 

     WordsterUser u = getItem(position); 

     TextView itw = (TextView) rv.findViewById(R.id.ItemTextView); 
     itw.setText(u.userName + " (" + u.loginName + ")"); 

     ImageView iv = (ImageView) rv.findViewById(R.id.SelectButton); 

     if (friendsListView.isItemChecked(position)) { 
      iv.setImageResource(R.drawable.downbutton); 
     } else { 
      iv.setImageResource(R.drawable.upbutton); 
     } 

     return rv; 
    } 
} 
+0

Dans votre exemple, comment l'instance 'FriendsAdapter' sait-elle ce que' friendsListView' fait référence? –

5

La solution est de créer une vue personnalisée qui implémente l'interface cliquable.

public class OneLineCheckableListItem extends LinearLayout implements Checkable { 

    public OneLineCheckableListItem(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    private boolean checked; 


    @Override 
    public boolean isChecked() { 
     return checked; 
    } 

    @Override 
    public void setChecked(boolean checked) { 
     this.checked = checked; 

     ImageView iv = (ImageView) findViewById(R.id.SelectImageView); 
     iv.setImageResource(checked ? R.drawable.button_up : R.drawable.button_down); 
    } 

    @Override 
    public void toggle() { 
     this.checked = !this.checked; 
    } 
} 

Et de créer une disposition personnalisée pour les éléments de liste utilisant le nouveau widget.

<?xml version="1.0" encoding="utf-8"?> 
<ax.wordster.OneLineCheckableListItem xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginBottom="4dp" 
    android:background="@drawable/selector_listitem" 
    android:orientation="horizontal" > 

    <ImageView 
     android:id="@+id/SelectImageView" 
     android:layout_width="60dp" 
     android:layout_height="60dp" 
     android:src="@drawable/button_friends_down" /> 

    <TextView 
     android:id="@+id/ItemTextView" 
     android:layout_width="fill_parent" 
     android:layout_height="60dp" 
     android:gravity="center" 
     android:text="@string/___" 
     android:textAppearance="?android:attr/textAppearanceLarge" 
     android:textColor="@color/text_item" /> 

</ax.wordster.OneLineCheckableListItem> 

Créez ensuite un nouvel adaptateur personnalisé en utilisant la disposition ci-dessus.

+0

Pourriez-vous m'aider: comment faire une sélection multiple pas sur un clic d'article, mais sur ImageView dans itemView et dans onItemClick je pourrais faire une autre action? – DavyJonesUA

+1

solutions simples et corrects .. – Ann

+0

ma condition est étrange, setChecked n'est pas appelé du tout, mais AbsListView.MultiChoiceModeListener # onItemCheckedStateChanged est appelé – HendraWD

1
+0

CheckableRelativeLayout d'Alvin Alexander rend la vue de niveau supérieur de la ligne vérifiable, y compris un bon état drawable android.R .attr.state_checked. Les drawables enfants tels que Checkbox peuvent utiliser cet état si vous leur transmettez l'état. Vous devez appliquer android: duplicateParentState = "true" à chaque enfant de CheckableRelativeLayout, y compris la case à cocher. – dschulten

Questions connexes