显然我的想法存在一些缺陷,因为它无法正常工作。基本上,我正试图解决这个问题:listview with checkbox
在答案中,人们建议创建一个全局数据结构来保持状态,这是有道理的。但是,我想如果我使用ViewHolder模式,我可以使用标签作为存储状态信息的结构吗?
cbox.setOnClickListener(new OnClickListener() {
public void onClick(View v)
{
P tag = (P) ((View) v.getParent()).getTag();
if(tag.cbox.isChecked())
tag.cbox.setChecked(true);
else
tag.cbox.setChecked(false);
//tag.cbox.toggle();
Log.d("YoYo", Boolean.toString(tag.cbox.isChecked()));
}
});
上面的代码没有在行中切换我的复选框。我做错了什么?
更新:而不是切换,手动if语句似乎有效。虽然,我遇到了另一个问题,在滚动到不同的地方后,检查状态陷入困境。这是为什么?如果我在tag.cbox中设置了checked状态,那么该对象的检查状态不是唯一的吗?
更新2:我遵循其他人的建议并获得了一个正常工作的版本,但我仍然想知道为什么setTag / getTag无效?
工作:
public View getView(final int position, View view, ViewGroup parent)
{
Plurker tag = getItem(position);
if (view == null)
view = adapterLayoutInflater.inflate(R.layout.adapter, null);
tag.avatar = (ImageView) view.findViewById(R.id.imgAvatar);
tag.cbox = (CheckBox) view.findViewById(R.id.cBox);
tag.cbox.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton btn, boolean isChecked)
{
int pos = position;
Plurker p = getItem(pos);
p.isChecked = isChecked;
Log.d("PLURK", "Listener:" + p.toString());
}
});
tag.update(getItem(position));
Log.d("PLURK", tag.cbox.getText() + ":" + Integer.toString(position));
return view;
}
不工作:
public View getView(final int position, View view, ViewGroup parent)
{
Plurker tag = getItem(position);
if (view == null)
{
view = adapterLayoutInflater.inflate(R.layout.adapter, null);
tag.avatar = (ImageView) view.findViewById(R.id.imgAvatar);
tag.cbox = (CheckBox) view.findViewById(R.id.cBox);
tag.cbox.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0)
{
int pos = position;
Plurker p = getItem(pos);
p.isChecked = !p.isChecked;
Log.d("PLURK", "Listener:" + p.toString());
}
});
view.setTag(tag);
}
else
tag = (Plurker) view.getTag();
tag.update(getItem(position));
Log.d("PLURK", tag.cbox.getText() + ":" + Integer.toString(position));
return view;
}
在“不工作”版本中,我需要使用onClick而不是onCheckedChanged事件,因为当隐藏的视图重新出现时,它会调用事件监听器,因此会错误地触发。
答案 0 :(得分:1)
您是每次都在为新视图充气还是使用传入的convertView?
通常,适配器会尝试回收视图,只能创建足够的视图以提供平滑滚动。现有的回收视图作为convertView传入。您可以每次充气并返回一个新视图(昂贵),或者只是根据位置重新设置convertView(如果存在)。如果回收,您需要重新设置所有视图属性,因为无法保证您获得的回收视图与过去用于此位置的视图相同。
听起来你的错误是你没有正确地重新设置循环视图的所有属性(convertView)以匹配当前位置的数据。