【问题标题】: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。我正在使用安卓工作室...

标签: java android listview


【解决方案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)”方法.....
猜你喜欢
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多