用于列表项更新的 ListView 适配器 onClickListener

ListView adapter onClickListener for list item update

我知道这个问题已经被问过很多次了。但在尝试了很多解决方案后,我无法成功实现它。

我正在制作一个包含多个 View 的自定义布局列表。其中一个视图是 ImageView,我希望它在用户单击它时更改其图标。

ListAdapter class我使用的是如下:

public class PetitionListAdapter extends BaseAdapter {

    ViewHolder holder = null;

    private LayoutInflater inflater;
    private ArrayList<CustomObject> objects;

    private class ViewHolder {
        ImageView ivsign;
    }

    public PetitionListAdapter(Context context, ArrayList<CustomObject> objects) {
        inflater = LayoutInflater.from(context);
        this.objects = objects;
    }

    public int getCount() {
        return objects.size();
    }

    public CustomObject getItem(int position) {
        return objects.get(position);
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(final int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            holder = new ViewHolder();
            convertView = inflater.inflate(R.layout.petition_list_layout_beta, null);
            holder.ivsign = convertView.findViewById(R.id.ivsign);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        holder.ivsign.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ImageView img = v.findViewById(R.id.ivsign);
                img.setImageResource(R.drawable.icon_after_click);
            }
        });
        return convertView;
    }
}

这样做,clickListener 起作用了,但它不是那个特定的 imageview,而是随机更改许多 imageview 的图标行。我知道它是因为 viewHolder。但是我怎样才能正确地做到这一点?

我也用过:-

imgViewArray[position] = holder.textView1;

里面 "onListItemClickListener"。这样做会根据需要更改该位置的图标,但在滚动并再次返回该行后,它再次更改为默认图标。我知道这是因为该行被回收了。

我认为你的问题出在你的 onClickListener 上。您在 ViewHolder 中为 ImageView 设置它,然后在 onClick 方法中设置 v.findViewById

你应该做的是

ImageView img = (ImageView) convertView.findViewById(R.id.ivsign);

然后

img.setOnClickListener(.......);

这对我有用,所以如果您在实施时遇到任何问题,请告诉我。

这不是好的做法。在 OnItemClick 中,您应该更改列表使用的对象列表,然后调用 notifyDataSetChanged()。在 getView(...) 中,您应该简单地使 listView 反映列表中的值。 这样,当列表刷新时,视图的状态保持不变。

是的,您当然遇到了这个问题。为什么?因为当滚动列表视图时,您所有的 convert view 都被重复使用,每个 convertView 用于显示另一个 CustomObject。这意味着如果您更改第一行图像,滚动后,重新使用 first-row convertView 的行将 image 显示为 clicked row。那么,如何解决呢?您必须在 CustomObject 中保存项目的位置,例如:

 public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.petition_list_layout_beta, null);
        holder.ivsign = convertView.findViewById(R.id.ivsign);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    final CustomObject object = listCustomObject.get(position);
    holder.ivsign.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ((ImageView)v).setImageResource(R.drawable.icon_after_click);
            object.saveResourceId(R.drawable.icon_after_click); // save your resource to use after scrolling.
        }
    });
    // display resouce base on what's saved or display default image.
    holder.ivSign.setImageResource(object.getSavedResourceId()); 
    return convertView;
}