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

时间:2017-11-06 16:18:39

标签: android listview onclicklistener android-viewholder

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

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

我使用的ListAdapter类如下:

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可以正常工作,但它会改变随机行中许多图像视图的图标,而不是特定的图像视图。我知道它因为viewHolder。但是我该怎么做呢?

我也曾使用过: -

  

imgViewArray [position] = holder.textView1;

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

3 个答案:

答案 0 :(得分:1)

是的,当然你遇到了这个问题。为什么?因为滚动列表视图时,所有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;
}

答案 1 :(得分:0)

我认为您的问题来自您的onClickListener。您是为ImageView中的ViewHolder设置的,然后是onClick方法v.findViewById内的ImageView img = (ImageView) convertView.findViewById(R.id.ivsign);

你应该做的是

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

然后

{{1}}

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

答案 2 :(得分:0)

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