滚动后如何保存和维护ListView项目状态?

时间:2014-04-23 14:38:05

标签: android listview android-listview selecteditem custom-adapter

在这里找到一些答案之后,我发现自己处于一个令人不安的境地,我的Listview真的让我神经紧张。

以下是我要查找的问题:

Maintain ListView Item State

How to save state of CheckBox while scrolling in ListView?

我使用自定义适配器和自定义行,如下所示。

我的Listview很简单,因为它显示了由三个元素组成的自定义行:

1)ImageView显示以圆圈裁剪的联系人图片;

2)TextView将联系人全名显示为纯文本;

3)最后是ImageView,其中包含CheckBox的purpouse。

请关注最后一个元素。 ImageView CheckBox将在点击时更改src。 当用户单击时,ImageView将根据其先前的状态在检查标志和未检查的标志之间切换。可能的状态是:{checked | unchecked}

到目前为止一切顺利。 但是当我滚动ListView时,任何前面提到的更改都会在Android回收未使用的视图时消失。 这就是所谓的ViewHolder模式。不幸的是,这种模式在两个问题上让我很烦恼:

首先,滚动时,我按字母顺序排列的列表视图变得杂乱无章。 例如不知怎的,不管怎么说,当我滚动时,第一个显示的联系人姓名会在ListView上再次显示。任何行都可能发生这种情况!因此,似乎未使用的视图被错误地重复使用。

其次,根据第一个问题,检查状态似乎确实存在,但并非总是如果它确实停留,它可能很好地保持在错误的行......这当然可以随机发生,当然。因此ViewHoder不是一个可行的解决方案。

在取消ViewHolder模式之前,我一直使用HashMap存储项目位置,如下所示:

ContactsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        public final void onItemClick(final AdapterView<?> adapterView, final View view,
                                          final int position, final long id) {

            final ImageView check = (ImageView) view.findViewById(R.id.checkImage);
            final TextView name = (TextView) view.findViewById(R.id.contactName);
            final Boolean isChecked = Boolean.valueOf(checkedContactsList.isChecked(position));

            if (isChecked != null && isChecked.booleanValue() == true) {
               check.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.unchecked_sign));
               checkedContactsList.(position);
            } else {
               check.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.checked_sign));
               checkedContactsList.add(position, true);
            }
        }
    });

我尝试添加其他值而不是position。 我试过ContactsListView.getPositionForView(view) 我也尝试使用View的ID,但它仍然无法正常工作。 我希望我可以使用ContactsListView.getSelectedItemPosition()但由于没有选择事件而返回-1,因为我正在处理触摸/点击事件。

这就是我Custom Adapter的样子:

public final View getView(final int position,
                          final View convertView, final ViewGroup parent) {
    final LayoutInflater inflater = (LayoutInflater) this.context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View contactRowView = inflater.inflate(R.layout.contact_row, parent, false);

    final ImageView contactPic = (ImageView) contactRowView.findViewById(R.id.contactPic);
    final TextView contactName = (TextView) contactRowView.findViewById(R.id.contactName);
    final ImageView checkImage = (ImageView) contactRowView.findViewById(R.id.checkImage);
    // the list is the same as above and therefore contains the exact same entries
    if (this.checkedContactsList.isChecked(position))
        checkImage.setImageDrawable(this.context.getResources().getDrawable(R.drawable.checked_sign));

    contactPic.setImageBitmap(cropePictureInCircle(this.contacts.get(position).getPicture()));
    contactName.setText(this.contacts.get(position).getName());
    return contactRowView;
}

是否有一种很好的方法可以检查选中的行,并且按照给定的字母顺序取消选中未选中的行?

谢谢!

1 个答案:

答案 0 :(得分:1)

对于列表位置更改我知道解决方案,但对于第二个问题我仍在寻找解决方案,无论如何首先创建一个viewHolder类;

 public class ViewHolder{
      //put all of your textviews and image views and 
      //all views here like this
      TextView contactName;
      ImageView checkImage;
      ImageView contactImage;
 }

然后编辑你的适配器:

@Override
public View getView(int position, View convertView, ViewGroup parent) 
{
    final View contactRowView = convertView;
    ViewHolder holder;
    if (contactRowView == null) {
        final LayoutInflater inflater = (LayoutInflater)
                this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE
                );

        contactRowView =
                inflater.inflate(R.layout.contact_row, parent,
                        false);
        holder = new ViewHolder():
        holder.contactPic = (ImageView)
                contactRowView.findViewById(R.id.contactPic);
        holder.contactName = (TextView)
                contactRowView.findViewById(R.id.contactName);
        holder.checkImage = (ImageView)
                contactRowView.findViewById(R.id.checkImage);
        contactRowView.setTag(holder);
    } else {
        holder = contactRowView.getTag();

        // the list is the same as above and therefore      contains the exact same entries
        if (this.checkedContactsList.isChecked(position))

            holder.checkImage.setImageDrawable(this.context.get.
                    Resources().getDrawable(R.drawable.checked_sign));


        holder.contactPic.setImageBitmap(cropePictureInCircle(this.contacts.get(position).getPicture()));

        holder.contactName.setText(this.contacts.get(position).getName());
        return contactRowView;
    }
}

希望这有帮助和抱歉,因为从我的手机编写代码非常尴尬。