2013-05-03 104 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(視圖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,您的複選框的setOnCheckedChangedListener必須早你checkbox.setChecked語句。

例如:

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

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

完美!感謝您的解釋。 – jthel 2013-05-03 13:51:15

+0

有趣,請問爲什麼checkchangelistener必須在setChecked之前?感謝 – 2015-03-15 05:57:38

+2

如果您想要在onCheckChanged做其他事情(如更新列表項的顏色等),如果調用設置監聽器之前setChecked就不會發生這些事情。 – josephus 2015-03-15 06:11:04

0

問題是因爲,列表視圖回收它認爲

所以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(); 

BTW:使用SparseBooleanArray而不是兩個列表存儲CheckedBox狀態。