2013-05-03 19 views
6

Mam pewne problemy z moim niestandardowym adapterem ListView (i jego nowo zaimplementowanym viewHolderem). Mam ListView z checkbox dla każdego elementu (nic nowego tutaj). Problem polega na tym, że jeśli na mojej liście znajduje się więcej niż 9 elementów, kiedy zaznaczę pierwsze pole wyboru, dziesiąta zostanie automatycznie sprawdzona (tak samo dla drugiej z jedenastą) tak, jakby istniał jeden słuchacz dla obu elementów (i ja uważać, że tak jest w pewnym sensie).Pole wyboru ViewView Viewholder:

czytałem o numerze pozycji z ListView, widok recyklingu i sposób ViewHolder rozwiązać go tutaj: How can I make my ArrayAdapter follow the ViewHolder pattern?

Ale zapewne coś złego, bo to nie działa ...

public class PresenceListAdapter extends SimpleAdapter { 
private LayoutInflater inflater; 
private List<Integer> ids; 
private List<String> statuts; 

public PresenceListAdapter (Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to, List<Integer> ids, List<String> statuts) 
{ 
    super (context, data, resource, from, to); 
    inflater = LayoutInflater.from (context); 
    this.ids = ids; 
    this.statuts= statuts; 

} 

@Override 
public Object getItem (int position) 
{ 
    return super.getItem (position); 
} 

@Override 
public View getView (int position, View convertView, ViewGroup parent) 
{ 

    ViewHolder holder; 

    if (convertView == null) 
    { 
     convertView = inflater.inflate (R.layout.list_text_checkbox, null); 

     holder = new ViewHolder(); 

     holder.btn = (Button) convertView.findViewById(R.id.btnRetard); 
     holder.check = (CheckBox) convertView.findViewById(R.id.checkPresent); 

     if (statuts.get(position).equals("P")) { 
      Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_online); 
      holder.btn.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null); 
      holder.btn.setEnabled(true); 
      holder.check.setChecked(true); 
     } 
     else if(statuts.get(position).equals("R")) 
     { 
      Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_away); 
      holder.btn.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null); 
      holder.btn.setEnabled(true); 
      holder.check.setChecked(true); 
     } 
     else 
     { 
      Drawable img = inflater.getContext().getResources().getDrawable(android.R.drawable.presence_invisible); 
      holder.btn.setCompoundDrawablesWithIntrinsicBounds(img, null, null, null); 
      holder.check.setChecked(false); 
     } 

     convertView.setTag(holder); 
    } 
    else 
    { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    int id = ids.get(position); 

    if(id != 0) 
    { 
     holder.check.setTag(id); 
     holder.btn.setTag(id); 
    } 

    return super.getView (position, convertView, parent); 
} 

static class ViewHolder { 
    Button btn; 
    CheckBox check; 
} 

I mój słuchacz: public void changerPresent (Zobacz v) {

CheckBox checkPresent = (CheckBox) v; 
    int idPersonne = (Integer) checkPresent.getTag(); 
    View parent = (View)v.getParent(); 
    Button btn = (Button) parent.findViewById(R.id.btnRetard); 

    if(checkPresent.isChecked()) { 
     gestion.updatePresence(idPersonne, idSeance, "P"); 

     btn.setEnabled(true); 
     setBtnRetardPresent(btn);   
    } 
    else 
    { 
     gestion.updatePresence(idPersonne, idSeance, "A"); 
     btn.setEnabled(false); 
     setBtnRetardAbsent(btn); 

    } 

} 

będę wdzięczny za każdą pomoc w tym momencie, jestem pracujemy nad tym od wielu godzin.

Dziękuję bardzo.

Odpowiedz

13

Oto jak zrobiłem to działa:

Po pierwsze, trzeba osobną tablicę dla swojej sprawdzonej stanu. Musi mieć ten sam rozmiar, co karta getCount() adaptera.

Następnie w swoim getView, checkbox setOnCheckedChangedListener MUSI WPISAĆ checkbox.setChecked wyciągi.

przykład:

holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
    isChecked[position] = isChecked; 
    } 
}); 

holder.checkBox.setChecked(isChecked[position]); 
+0

Perfect! Dziękuję za wyjaśnienia. – jthel

+0

Interesujące, czy możesz powiedzieć, dlaczego checkchangelistener musi poprzedzać setChecked? Dzięki –

+2

jeśli masz inne rzeczy, które chcesz zrobić w onCheckChanged (takie jak aktualizacja koloru elementu listy itp.), Te rzeczy nie będą miały miejsca, jeśli zadzwonisz setChecked przed ustawieniem detektora. – josephus

0

Problemem jest to, ze względu na fakt, że ListView zasypki postrzega

więc w getView() Metoda

 if (convertView == null) 
     { 
    ........ 
     } 
    else 
     { 
      holder = (ViewHolder) convertView.getTag(); 


     } 
    // Uncheck needed boxes here... You need to implement your logic 
     if('position' is checked earlier) 
     holder.check.setChecked(true); 
     else 
     holder.check.setChecked(false); 

Musisz napisać kod do zarządzania stan widzenia jeśli konwersja nie jest null , ponieważ jest to już używany widok, który może mieć zaznaczone pola wyboru.

0

należy ustawić stan CheckedBox poza inicjalizacji ViewHolder, jak następujący kod:

if (convertView == null) { 
    viewHolder = new ViewHolder(); 
    convertView.setTag(viewHolder); 
} else { 
    viewHolder = (ViewHolder) convertView.getTag(); 
} 

viewHolder.checkedBox.setChecked(); 

BTW: wykorzystywać SparseBooleanArray zamiast dwa listy do przechowywania stanu CheckedBox.

Powiązane problemy