ListView使用Tag维护状态?

时间:2012-02-29 06:28:55

标签: android listview checkbox

显然我的想法存在一些缺陷,因为它无法正常工作。基本上,我正试图解决这个问题: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事件,因为当隐藏的视图重新出现时,它会调用事件监听器,因此会错误地触发。

1 个答案:

答案 0 :(得分:1)

您是每次都在为新视图充气还是使用传入的convertView?

通常,适配器会尝试回收视图,只能创建足够的视图以提供平滑滚动。现有的回收视图作为convertView传入。您可以每次充气并返回一个新视图(昂贵),或者只是根据位置重新设置convertView(如果存在)。如果回收,您需要重新设置所有视图属性,因为无法保证您获得的回收视图与过去用于此位置的视图相同。

听起来你的错误是你没有正确地重新设置循环视图的所有属性(convertView)以匹配当前位置的数据。