【问题标题】:Remove a item from a RecyclerView (ViewHolder has the onClick but adapter has the dataset)从 RecyclerView 中删除一个项目(ViewHolder 有 onClick 但适配器有数据集)
【发布时间】:2018-08-08 19:10:59
【问题描述】:

当按下项目中的视图时,我想从回收站视图中删除项目。

情况:使用带有数据集的 RecyclerView 和 ViewHolder 制作列表,该列表具有 onClick 用于从列表中删除项目的视图,我需要知道单击了哪个项目在 ViewHolder 上并将其传递给 Adapter,因为 Adapter 具有数据集。在 ViewHolder 中我可以通过这个方法知道哪个项目被按下了:getAdapterPosition(),所以似乎很容易知道要删除哪个项目。

问题: ViewHolderRecyclerView.Adapter 内部的一个子类,并且 Adapter 有数据集,所以我试图了解哪个是查看者与必须删除已被点击的 Item 的适配器。

最先进的技术:我可以在 Stack Overflow 中看到一些问题,其中一些是旧的,其中一些是新的,例如:Android RecyclerView addition & removal of items 但解决方案没有说明如何与必须删除项目的适配器通信。可能用户正在使用静态字段或其他东西来做这件事,但这不是实现这一目标的好方法。而且我看不到其他问题中解释的其他方式。

这是来自官方 Recycler 指南的示例,您可以在其中看到 ViewHolder 嵌套在 Adapter 内部并且无法访问它:https://developer.android.com/guide/topics/ui/layout/recyclerview.html

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private String[] mDataset;

    // Provide a reference to the views for each data item
    // Complex data items may need more than one view per item, and
    // you provide access to all the views for a data item in a view holder
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;
        public ViewHolder(TextView v) {
            super(v);
            mTextView = v;
        }
    }

    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(String[] myDataset) {
        mDataset = myDataset;
    }

    // Create new views (invoked by the layout manager)
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        TextView v = (TextView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.my_text_view, parent, false);
        ...
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    // Replace the contents of a view (invoked by the layout manager)
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        holder.mTextView.setText(mDataset[position]);

    }

    // Return the size of your dataset (invoked by the layout manager)
    @Override
    public int getItemCount() {
        return mDataset.length;
    }
}

【问题讨论】:

  • y 没有在onBindViewHolder(..) 中设置点击,而是在那里我们将位置作为参数
  • @SantanuSur 请解释一下,我不明白你的意思
  • 你可以在你的onBindViewHolder()里面放一个onClickListener而不是你的ViewHolder类。
  • 我们可以在onBindViewHolder(ViewHolder holder, int position) { holder.setonClick(.....onClick(View view) { this.notifyItemRemoved(position); }} 中设置clickListener 不行吗??
  • ViewHolder 不应该进行任何通信。它是视图的查找表,是对重复调用 findViewById 的优化。它根本不应该有任何逻辑。

标签: android android-recyclerview android-viewholder


【解决方案1】:

我喜欢RecyclerView example by BigNerdRanch,因为他们有一个自定义的ViewHolder 和一个从onBindViewHolder() 调用的方法(示例中为bindCrime())。此方法从数据列表中获取一个项目,并根据项目的内容设置所有Views。

您可以使用类似的方法,我们称之为bindData(),不仅传入数据列表中的项目,还传入自定义回调的[匿名实例],我们称之为ViewHolderCallback,它位于其实只是一些界面:

interface ViewHolderCallback{
    void itemWasClicked(int position);
}

那么onBindViewHolder() 可能看起来像这样:

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    // - get element from your dataset at this position
    // - replace the contents of the view with that element
    holder.bindData(mDataset[position], new ViewHolderCallback(){

        @Override
        public void itemWasClicked(int position){
             // remove the item 
        }
    });
}

...和bindData() 像这样:

void bindData(String text, ViewHolderCallback callback){
    mTextView.setText(text);
    itemView.setOnClickListener(new View.OnClickListener(){
         
        @Override
        public void onClick(View view){
             callback.itemWasClicked(getAdapterPosition()); 
        }
    });
}

【讨论】:

    【解决方案2】:

    最后我用更简单的方法解决了,我只是在适配器的onBindViewHolder方法中添加了删除项目的监听器:

    @Override
    public void onBindViewHolder(final ViewHolder holder, final int position) {
        holder.trashImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onDeleteClick(view.getContext(), position);
                notifyItemRemoved(position);
                notifyItemRangeChanged(position, mDataset.size());
            }
        });
    }
    

    像魅力一样工作

    【讨论】:

      猜你喜欢
      • 2017-09-06
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      相关资源
      最近更新 更多