【问题标题】:Deleting items from a ListView using a custom BaseAdapter使用自定义 BaseAdapter 从 ListView 中删除项目
【发布时间】:2011-01-04 02:48:22
【问题描述】:

我正在使用定制的 BaseAdapter 在 ListView 上显示项目。这些项目只是保存在 ArrayList 中的字符串。

列表项上有一个删除按钮(大红色 X),我想从 ArrayList 中删除该项,并通知 ListView 自行更新。

但是,我尝试过的每个实现都会获得神秘的位置编号,因此例如单击项目 2 的删除按钮将删除项目 5。它似乎几乎完全是随机的。

需要注意的一点是元素可以重复,但必须保持相同的顺序。例如,我可以有两次“爱尔兰语”,分别作为元素 3 和 7。

我的代码如下:

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;
}

我稍后尝试通过抓取标签来检索已删除元素的位置,但它总是在列表中的错误位置。这里给出的位置没有明显的规律,它似乎总是随机的。

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

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

    ...
    ...
    ...
}

我很乐意从 ArrayList 中删除项目并让 ListView 自行更新,但我得到的位置不正确,所以我不能这样做。

请注意,起初我确实在 getView 方法中使用了 deleteButton clickListener,并使用 'position' 删除了值,但我遇到了同样的问题。

感谢任何建议,这真的让我很恼火。

【问题讨论】:

    标签: android listview android-listview


    【解决方案1】:

    您必须每次设置位置。您的实现仅设置视图创建的位置。但是当视图被回收时(当convertView不为null时),位置将不会被设置为正确的值。

        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】:

    你需要实现OnItemClickListener接口,并在onItemClick方法中删除项目,该方法的一个参数是位置。

    【讨论】:

    • 他有一个按钮,这样听者就不合适了。该监听器仅在整个列表元素接收到点击事件时才起作用。
    【解决方案3】:

    我的最终解决方案是使用 Greg 接受的答案以及以下内容:

    • 将持有者存储在 HashMap 中,以项目位置作为键(在构造函数中初始化为空)

      私有HashMap mHolders;

    • 将其用作 onClickListener 方法:

    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();
    }
    

    [请原谅奇怪的格式。代码嵌入不正常]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多