我的列表视图上的删除按钮无法正常工作

Posted

技术标签:

【中文标题】我的列表视图上的删除按钮无法正常工作【英文标题】:Delete button on my listview is not working as it is supposed to 【发布时间】:2021-07-08 05:33:02 【问题描述】:

所以我想在列表的每个项目上都有一个删除按钮,这样当按下该按钮时,我希望完全删除该特定列表项。但是,当我尝试这样做时,它不起作用。此外,如果我两次单击删除图标,应用程序就会崩溃。 这是我的列表适配器的代码:

    package com.example.taskmasterv3;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.ArrayList;

public class SubtaskAdapter extends ArrayAdapter<subtask> 


    private final Context context;
    private ArrayList<subtask> values;


    public SubtaskAdapter(Context context, ArrayList<subtask> list) 

        //since your are using custom view,pass zero and inflate the custom view by overriding getview
    super(context, 0 , list);
    this.context = context;
    this.values = list;




@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) 

    //check if its null, if so inflate it, else simply reuse it
    if (convertView == null) 
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = inflater.inflate(R.layout.subtask_item, parent, false);
    

    //use convertView to refer the childviews to populate it with data
    TextView tvSubtaskName = convertView.findViewById(R.id.tvSubtaskName);
    ImageView ivPri = convertView.findViewById(R.id.ivPri);
    ImageView ivTime = convertView.findViewById(R.id.ivTime);
    ImageView ivDelete = convertView.findViewById(R.id.ivDelete);

    tvSubtaskName.setText(values.get(position).getSubtaskName());

    if (values.get(position).isPriHigh()) 
        ivPri.setImageResource(R.drawable.priority_high);
     else if (values.get(position).isPriMed()) 
        ivPri.setImageResource(R.drawable.priority_med);
     else if (values.get(position).isPriLow()) 
        ivPri.setImageResource(R.drawable.priority_low);
    

    if (values.get(position).isTimeMore()) 
        ivTime.setImageResource(R.drawable.time_symbol_more);
     else if (values.get(position).isTimeMed()) 
        ivTime.setImageResource(R.drawable.time_symbol_med);
     else if (values.get(position).isTimeLess()) 
        ivTime.setImageResource(R.drawable.time_symbol_less);
    


    // Delete button for subtasks (NOT WORKING)

    ivDelete.setOnClickListener(new View.OnClickListener() 
        @Override
        public void onClick(View v) 

            values.remove(position);
            notifyDataSetChanged();
        
    );

    //return the view you inflated
    return convertView;






//to keep adding the new subtasks try the following
public void addANewSubTask(subtask newSubTask)
    ArrayList<subtask> newvalues = new ArrayList<>(this.values);
    newvalues.add(newSubTask);
    this.values = newvalues;
    notifyDataSetChanged();


【问题讨论】:

removeAt 对你有用吗? 我没有看到任何这样的选项。我看到的是 remove、removeAll、removeIf。我正在使用安卓工作室... 【参考方案1】:

values.remove(position); 更改为values.remove(values.get(position));

【讨论】:

是的,现在似乎已修复,但我现在面临的问题是删除按钮会自动删除列表的最后一项,而不是我想要删除的特定项目。有什么解决办法吗?【参考方案2】:

由于继续创建 OnClickListener 并使用 findViewById() 解析视图 ID,以这种方式使用 ListView 非常糟糕并且内存很重。 侵入性较小的解决方案是使用缓存所有 View ID 和 ClickListener 的 ViewHolder:

public class SubtaskAdapter extends ArrayAdapter<subtask> 

    private final LayoutInflater mLayoutInflater;

    public SubtaskAdapter(@NonNull final Context context, @NonNull final List<subtask> values) 
        super(context, R.layout.subtask_item, values);
        this.mLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    

    private static class ViewHolder 
        private int mPosition = -1;
        private final TextView tvSubtaskName;
        private final ImageView ivPri;
        private final ImageView ivTime;
        private final ImageView ivDelete;
        private final View.OnClickListener mOnClickListener;
        private ViewHolder(@NonNull final ArrayAdapter<subtask> arrayAdapter, @NonNull final View convertView) 
            this.tvSubtaskName = convertView.findViewById(R.id.tvSubtaskName);
            this.ivPri = convertView.findViewById(R.id.ivPri);
            this.ivTime = convertView.findViewById(R.id.ivTime);
            this.ivDelete = convertView.findViewById(R.id.ivDelete);
            this.mOnClickListener = new View.OnClickListener() 
                @Override
                public void onClick(final View v) 
                    arrayAdapter.remove(arrayAdapter.getItem(ViewHolder.this.mPosition));
                    arrayAdapter.notifyDataSetChanged();
                
            ;
            this.ivDelete.setOnClickListener(this.mOnClickListener);
        
        private void setPosition(final int position)  this.mPosition = position; 
    

    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull final ViewGroup parent) 
        final View cParentView = super.getView(position, convertView, parent);
        if (cParentView != null) return cParentView;
        ViewHolder holder;

        if (convertView == null) 
            convertView = this.mLayoutInflater.inflate(R.layout.subtask_item, parent, false);
            holder = new ViewHolder(this, convertView);
            convertView.setTag(holder);
         else 
            holder = (ViewHolder)convertView.getTag();
        
        holder.setPosition(position);
        
        final subtask cCurrentSubtask = getItem(position);

        holder.tvSubtaskName.setText(cCurrentSubtask.getSubtaskName());

        if (cCurrentSubtask.isPriHigh()) 
            holder.ivPri.setImageResource(R.drawable.priority_high);
         else if (cCurrentSubtask.isPriMed()) 
            holder.ivPri.setImageResource(R.drawable.priority_med);
         else if (cCurrentSubtask.isPriLow()) 
            holder.ivPri.setImageResource(R.drawable.priority_low);
        

        if (cCurrentSubtask.isTimeMore()) 
            holder.ivTime.setImageResource(R.drawable.time_symbol_more);
         else if (cCurrentSubtask.isTimeMed()) 
            holder.ivTime.setImageResource(R.drawable.time_symbol_med);
         else if (cCurrentSubtask.isTimeLess()) 
            holder.ivTime.setImageResource(R.drawable.time_symbol_less);
        
        
        return convertView;
    

您不需要使用内部“值”来保存所有项目,您可以使用“ArrayAdapter.add()”和其他类似方法(remove()、getItem()、getCount() 等)在您创建 ArrayAdapter 并传递初始 Items Array/List 之后。

编辑:要将项目添加到 ArrayAdapter,您需要保存 ArrayAdapter 实例,然后调用其“add()”方法。

public class MainActivity extends Activity 
    ...
    @Nullable
    private SubtaskAdapter mSubtaskAdapter = null;
    @Override
    protected void onCreate(@Nullable final Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSubtaskAdapter = new SubtaskAdapter(this, subtask_items);
    
    private boolean addSubtaskToList(@Nullable final subtask newSubtask) 
        if ((mSubtaskAdapter == null) || (newSubtask == null)) return false;
        mSubtaskAdapter.add(newSubtask);
        return true;
    

【讨论】:

感谢您的建议。但是我在当前代码中实现这一点时遇到了麻烦。我还是编程新手。你能帮我一下吗 另外,删除功能仍然不适合我 我在答案中添加了最终评论。您不需要 ArrayAdapter 中的“值”,但您可以通过传递初始 Array/List 来创建 ArrayAdapter,然后使用它自己的 add()、addAll()、remove()、getCount()、getItem() 等... 方法(ArrayAdapter 本身使用内部 ArrayList 好的。所以现在我正在使用这个: SubtaskAdapter.this.remove() ,但是在删除后的括号内,它说我必须放入一个子任务对象。如何在此处引用用户尝试删除的列表项? 是的,这有点奇怪,但在您的情况下应该使用“SubtaskAdapter.this.remove(SubtaskAdapter.this.getItem(position))”来完成。不知道为什么Adapter没有暴露一个简单的“remove(index)”方法.....

以上是关于我的列表视图上的删除按钮无法正常工作的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的列表视图上的删除按钮不起作用[重复]

“对话框”内的列表视图中的复选框无法正常工作

应用于字幕表视图单元格的 UITableViewAutomaticDimension 无法正常工作

我的自定义搜索视图无法正常工作,当搜索输入为空时不显示原始列表

Android:自定义列表视图无法正常工作

无法从 superview-Xcode6 中删除子视图