2011-08-26 6 views
15

Ho un ListView che visualizza 2 tipi di elementi. Uno di questi tipi contiene CheckedTextView. Come adattatore sto usando un adattatore personalizzato che estende ArrayAdapter con una struttura dati contenente informazioni sugli stati controllati/non selezionati all'interno.Impostazione ListView elemento controllato dall'adattatore

Alcuni degli elementi sono contrassegnati come selezionati (nella mia struttura dati), quindi ovviamente vorrei che le caselle di controllo vengano contrassegnate quando viene creato il ListView. Ho provato a farlo sul metodo getView() nell'adattatore con il metodo setChecked() di CheckedTextView ma non funziona. Ho trovato informazioni che dovrebbero essere fatte a livello di ListView con setItemChecked() e funziona, ma non ha senso per me perché per farlo funzionare dovrei fare un ciclo di tutti gli elementi in attività suCreate() chiamando setItemChecked() per quelli selezionati. L'elenco degli articoli potrebbe essere molto lungo con solo alcuni selezionati, quindi è uno spreco.

Perché chiamare setChecked() in getView() non funziona? C'è un modo migliore per farlo (sono un principiante di Android).

Di seguito è riportato il layout dell'articolo selezionato e l'adattatore.

Disposizione:

<?xml version="1.0" encoding="utf-8"?> 
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" 
    android:gravity="center_vertical" 
    android:textAppearance="@style/listViewItemText" 
    android:checkMark="?android:attr/listChoiceIndicatorMultiple" 
    android:paddingLeft="6dp" 
    android:paddingRight="6dp" 
/> 

Adapter:

package com.melog.re.droid.search; 

import java.util.ArrayList; 
import java.util.List; 

import android.content.Context; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ArrayAdapter; 
import android.widget.CheckedTextView; 
import android.widget.TextView; 

import com.melog.re.droid.core.R; 
import com.melog.re.droid.search.MultiCriterionValue.MultiCriterionSingleValue; 
import com.melog.re.droid.search.MultiListAdapter.MultiChoiceItem; 

public class MultiListAdapter extends ArrayAdapter<MultiChoiceItem> { 
    private static final int VIEW_TYPES_COUNT = 2; 

    public static final int VIEW_TYPE_GROUP = 0; 
    public static final int VIEW_TYPE_ITEM = 1; 

    private LayoutInflater mInflater; 

    public MultiListAdapter(Context context, int textViewResourceId, List<MultiChoiceItem> objects) { 
     super(context, textViewResourceId, objects); 
     mInflater = LayoutInflater.from(context); 
    } 

    @Override 
    public int getItemViewType(int position) { 
     MultiChoiceItem item = getItem(position); 
     return (item.children.size() == 0) ? VIEW_TYPE_ITEM : VIEW_TYPE_GROUP; 
    } 

    @Override 
    public int getViewTypeCount() { 
     return VIEW_TYPES_COUNT; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     // TODO: optymalizacja ViewHolder 
     MultiChoiceItem item = getItem(position); 
     int viewType = getItemViewType(position); 
     switch (viewType) { 
     case VIEW_TYPE_GROUP: 
      if (convertView == null) { 
       convertView = mInflater.inflate(R.layout.multi_choice_group_item, parent, false); 
      } 
      TextView groupLabel = (TextView) convertView.findViewById(android.R.id.text1); 
      groupLabel.setText(item.toString()); 
      break; 
     case VIEW_TYPE_ITEM: 
      if (convertView == null) { 
       convertView = mInflater.inflate(R.layout.multi_choice_child_item, parent, false); 
      } 
      CheckedTextView itemLabel = (CheckedTextView) convertView.findViewById(android.R.id.text1); 
      itemLabel.setText(item.toString()); 
      itemLabel.setChecked(item.selected); 
      break; 
     } 

     return convertView; 
    } 

    public static class MultiChoiceItem implements Parcelable { 
     public static final int CONTENTS_DESCR = 1; 

     public String label; 
     public String value; 
     public boolean selected = false; 
     public ArrayList<MultiChoiceItem> children = new ArrayList<MultiChoiceItem>(); 

     public MultiChoiceItem(String l, String v, boolean sel) { 
      label = l; 
      value = v; 
      selected = sel; 
     } 
     public MultiChoiceItem(MultiCriterionSingleValue v) { 
      label = v.toString(); 
      value = v.value; 
     } 
     public MultiChoiceItem(Parcel in) { 
      label = in.readString(); 
      value = in.readString(); 
      selected = (in.readInt() == 1); 
     } 
     @Override 
     public String toString() { 
      return label; 
     } 
     @Override 
     public int describeContents() { 
      return CONTENTS_DESCR; 
     } 
     @Override 
     public void writeToParcel(Parcel dest, int flags) { 
      dest.writeString(label); 
      dest.writeString(value); 
      dest.writeInt(selected ? 1 : 0); 
     } 

     public static final Parcelable.Creator<MultiChoiceItem> CREATOR = new Parcelable.Creator<MultiChoiceItem>() { 
      public MultiChoiceItem createFromParcel(Parcel in) { 
       return new MultiChoiceItem(in); 
      } 

      public MultiChoiceItem[] newArray(int size) { 
       return new MultiChoiceItem[size]; 
      } 
     }; 
} 
} 

E un pezzo di onCreate di attività()

...  
mAdapter = new MultiListAdapter(this, R.id.head, mItems); 
setListAdapter(mAdapter); 

final ListView listView = getListView(); 
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 
listView.setItemsCanFocus(false); 
... 

Edit:

fino a trovare una soluzione migliore ho implementato il controllo ing in attività:

... 
int len = mListView.getCount(); 
for (int i = 0; i < len; i++) { 
    if (((MultiChoiceItem) mListView.getItemAtPosition(i)).selected) { 
     mListView.setItemChecked(i, true); 
    } 
} 
... 

ho pensato che le prestazioni saranno l'unico problema potenziale, ma ho trovato un altro - molto più grave. L'elenco ha il filtro di testo abilitato (mListView.setTextFilterEnabled (true)). Ecco lo scenario fallimento:

  1. apro nuova lista
  2. Im controllo diciamo voce 2-nd
  3. mi metto a digitare per filtrare alcuni oggetti
  4. quando il filtraggio viene eseguito, il 2- ND oggetto è ancora verificata, anche se non è quello che ho controllato

Suppongo che setItemChecked() segna una posizione fissa sulla lista controllato mentre ho bisogno di qualcosa che segnerà la voce tenutasi il posizione tHS - mantenere lo stato anche quando la posizione sulla lista cambia.

Mentre il problema delle prestazioni potrebbe essere (fino ad un certo punto) ignorato, questo nuovo problema mi sta davvero bloccando, quindi sarei davvero grato di aiutarlo.

risposta

28

Se si utilizza ListView.CHOICE_MODE_MULTIPLE o CHOICE_MODE_SINGLE gli stati di controllo degli elementi saranno sovrascritti da ListView dopo getView viene chiamato. Devi usare il seguente costrutto:

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    ((ListView)parent).setItemChecked(position, true); 
} 

Un altro possiblity è quello di utilizzare ListView.CHOICE_MODE_NONE e gestire gli stati di controllo da soli.

+0

Sto affrontando con lo stesso problema.I miei elementi selezionati scompaiono quando si scorre il listview.Ho provato il codice blok all'interno del mio adattatore, ma ancora i miei elementi selezionati stanno scomparendo quando si scorre la listview – salih

+0

Grazie, ho dovuto cercare un po ' tempo per trovare una soluzione. –

-1

Scopri i passi Prima in oggetto XML apportare le modifiche aggiungere singola riga nella casella di controllo

`android:onClick="chatWithFriend"` 

in modo che quando il clic su cheackbox quindi creare l'un metodo in nome dell'attività

public void chatWithFriend(View view){} 
here you will get the view of check box, 

Ora aggiungi la riga in getView prima del ritorno converti vista

holder.checkbox .setTag (posizione);

Ora u otterrà la posizione della casella di controllo

Spero che questo vi aiuterà.

+0

Forse non mi sono chiarito. Non ho alcun problema con ottenere la posizione dell'oggetto. Tutte le azioni "click" funzionano bene. Ciò che non funziona sta rendendo gli elementi selezionati (queste informazioni sono nei dati passati all'adattatore) controllati nella visualizzazione elenco appena creata. – Izydorr

+0

questo può aiutare http://about-android.blogspot.com/2010/04/steps-to-implement-expandablelistview.html –

+0

Mi dispiace ma non vedo come questo potrebbe essere utile per me :( – Izydorr