web-dev-qa-db-fra.com

Liste à choix multiples avec vue personnalisée?

J'ai vu l'exemple com.example.Android.apis.view.List11 d'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.

Maintenant, je veux que chaque vue ait 2 TextView et 1 CheckBox, quelque peu similaire à l'exemple List. J'ai essayé de créer un fichier de mise en page personnalisé 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>

Ensuite, dans onCreate() de Activity, j'aime 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 à ce que je veux, mais il semble que la liste ne sache pas quel élément est sélectionné. De plus, je dois cliquer exactement sur le CheckBox. Dans l'exemple List11, je n'ai qu'à cliquer sur la ligne de l'élément.

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

34
Phil

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

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

17
Fernando Gallego

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 vous-même les événements de vérification/décocher.

Vous pouvez remplacer la onListItemCLick() de la 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 définissez pas ListView sur CHOICE_MODE_MULTIPLE, Car cela fait des choses étranges lors de l'appel de la fonction.

Pour récupérer la liste des lignes cochées, vous devez implémenter une méthode vous-même, appeler getCheckItemIds() sur 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
   }
}
7
JVitela

La solution consiste à créer une vue personnalisée qui implémente l'interface Clickable.

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 créez une mise en page personnalisée pour les éléments de la liste à l'aide du 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.

5
Adorjan Princz

Chacune de ces vues a un TextView et un CheckBox.

Non, non. Il a un CheckedTextView.

Alors, que dois-je faire pour créer une liste à choix multiples avec ma vue personnalisée pour chaque ligne?

Essayez de créer le CheckBoxAndroid:id valeur soit "@Android:id/text1" et voyez si cela aide. Il s'agit de l'ID utilisé par Android pour le CheckedTextView dans simple_list_item_multiple_choice.

5
CommonsWare
1
russellhoff

Exemple simple pour faire fonctionner une mise en page personnalisée en tant que 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;
    }
}
1
Adorjan Princz

C'est possible par une astuce

dans votre méthode ListActivtyClass

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

maintenant en vous l'adaptateur personnalisé

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;
    }

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

1
Rahul Garg

Vous avez la solution ... Vous pouvez obtenir les clics sur les vues (comme les cases à cocher dans les dispositions de ligne personnalisées) en ajoutant un écouteur à chacune d'entre elles dans l'adaptateur lui-même pendant que vous retournez la vue convertie dans getView (). Vous devrez peut-être passer une référence d'objet de liste si vous avez l'intention d'obtenir des informations spécifiques à une liste. comme l'ID de ligne.

0
Pritam

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 la fonction getView() de l'adaptateur).

Vous pouvez créer une nouvelle onClickListener() pour chaque élément, ou demander à l'adaptateur d'implémenter onClickListener() - dans ce cas, les éléments doivent être balisés pour que l'auditeur sache sur quel élément il fonctionne.

S'appuyer sur la liste onItemClickListener() - comme quelqu'un l'a conseillé dans un autre thread - ne fonctionnera pas car CheckBox interceptera l'événement click, donc la liste ne l'aura pas.

Et enfin @Rahul et JVitella:

La situation est que le CheckBox sur un élément de liste doit être cliquable et vérifiable indépendamment de l'élément de liste lui-même. Par conséquent, la solution est celle que je viens de décrire ci-dessus.

0
Yar