2013-05-03 3 views
6

У меня есть некоторые проблемы с моим адаптером ListView (и его новым реализованным viewHolder). У меня есть ListView с флажком для каждого элемента (ничего нового здесь). Проблема в том, что, если в моем списке больше 9 элементов, когда я проверяю первый флажок, десятая будет автоматически проверена (такая же для второй с одиннадцатой), как если бы был один прослушиватель для обоих элементов (и я быть верным, так или иначе).Состояние флажка ListView Viewholder

Я прочитал о проблеме позиции с ListView, вид переработки и пути ViewHolder решить его здесь: How can I make my ArrayAdapter follow the ViewHolder pattern?

Но я, вероятно, сделал что-то неправильно, потому что это не работает ...

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

И мой слушатель: общественного недействительный changerPresent (View 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); 

    } 

} 

Я был бы признателен за любую помощь в этом пункте, я работая над этим в течение нескольких часов.

спасибо.

ответ

13

Вот как я сделал это работает:

Во-первых, вам нужен отдельный массив для зарегистрированном состояния. Он должен быть того же размера, что и ваш адаптер getCount().

Затем на вашем getView установленный вами checkbox setOnCheckedChangedListener ДОЛЖЕН ПРЕКРАТИТЬ ваши checkbox.setПроверенные заявления.

пример:

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

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

Отлично! Спасибо за ваши объяснения. – jthel

+0

Интересно, не могли бы вы рассказать, почему checkchangelistener должен предшествовать setChecked? Спасибо –

+2

, если у вас есть другие вещи, которые вы хотите сделать в onCheckChanged (например, обновите цвет элемента списка и т. Д.), Это не произойдет, если вы вызываете setChecked перед установкой слушателя. – josephus

0

Проблема заключается в том, из-за того, что ListView перерабатывает он рассматривает

так в getView() метод

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

Вам нужно написать код для управления состоянием зрения, если новообращенный не является нулевым , потому что это уже используемое представление, которое может иметь проверочные флажки.

0

Вы должны установить CheckedBox состояние вне инициализации ViewHolder, как следующий код:

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

viewHolder.checkedBox.setChecked(); 

КСТАТИ: использовать SparseBooleanArray вместо два списка для хранения CheckedBox состояния.

Смежные вопросы