Deleting items from a ListView using a custom BaseAdapter

妖精的绣舞 提交于 2019-12-03 13:00:07

问题


I am using a customised BaseAdapter to display items on a ListView. The items are just strings held in an ArrayList.

The list items have a delete button on them (big red X), and I'd like to remove the item from the ArrayList, and notify the ListView to update itself.

However, every implementation I've tried gets mysterious position numbers given to it, so for example clicking item 2's delete button will delete item 5's. It seems to be almost entirely random.

One thing to note is that elements may be repeated, but must be kept in the same order. For example, I can have "Irish" twice, as elements 3 and 7.

My code is below:

private static class ViewHolder {
        TextView lang;
        int position;
}

public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.language_link_row, null);
        holder = new ViewHolder();
        holder.lang = (TextView)convertView.findViewById(R.id.language_link_text);
        holder.position = position;

        final ImageView deleteButton = (ImageView) 
                convertView.findViewById(R.id.language_link_cross_delete);
        deleteButton.setOnClickListener(this);

        convertView.setTag(holder);
        deleteButton.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.lang.setText(mLanguages.get(position));

    return convertView;
}

I later attempt to retrieve the deleted element's position by grabbing the tag, but it's always the wrong position in the list. There is no noticeable pattern to the position given here, it always seems random.

// The delete button's listener
public void onClick(View v) {

    ViewHolder deleteHolder = (ViewHolder) v.getTag();
    int pos = deleteHolder.position;

    ...
    ...
    ...
}

I would be quite happy to just delete the item from the ArrayList and have the ListView update itself, but the position I'm getting is incorrect so I can't do that.

Please note that I did, at first, have the deleteButton clickListener inside the getView method, and used 'position' to delete the value, but I had the same problem.

Any suggestions appreciated, this is really irritating me.


回答1:


You have to set the position each time. Your implementation only sets the position on the creation of the view. However when the view is recycled (when convertView is not null), the position will not be set to the correct value.

    public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.language_link_row, null);
        holder = new ViewHolder();
        holder.lang = (TextView)convertView.findViewById(R.id.language_link_text);

        final ImageView deleteButton = (ImageView) 
                convertView.findViewById(R.id.language_link_cross_delete);
        deleteButton.setOnClickListener(this);

        convertView.setTag(holder);
        deleteButton.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.lang.setText(mLanguages.get(position));
    holder.position = position;
    return convertView;
}



回答2:


you need to implement OnItemClickListener interface, and delete the item in the onItemClick method, one parameter of the method is the position.




回答3:


My final solution was to use the accepted answer by Greg and the following:

  • Store the holders in a HashMap, with the item positions as the keys (this is initialised as empty in the constructor)

    private HashMap mHolders;

  • Use this as the onClickListener method:

public void onClick(View v) {
    ViewHolder deleteHolder = (ViewHolder) v.getTag();
    int pos = deleteHolder.position;
    mHolders.remove(pos);

    ViewHolder currentHolder;

    // Shift 'position' of remaining languages 
    // down since 'pos' was deleted
    for(int i=pos+1; i<getCount(); i++){
        currentHolder = mHolders.get(i);
        currentHolder.position = i-1;
    }
    mLanguages.remove(pos);
    notifyDataSetChanged();
}

[Please excuse the weird formatting. The code embedding isn't working properly]



来源:https://stackoverflow.com/questions/4590253/deleting-items-from-a-listview-using-a-custom-baseadapter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!