2013-05-03 100 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状态。