【问题标题】:Set onItemClickListener inside onBindViewHolder() with RecyclerView.Adapter使用 RecyclerView.Adapter 在 onBindViewHolder() 中设置 onItemClickListener
【发布时间】:2015-12-22 04:36:46
【问题描述】:

我有一个自定义对象:

学生班

public class Student {
  private String name;
  private String age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAge() {
    return age;
  }

  public void setAge(String age) {
    this.age = age;
  }
}

然后我像这样实现RecyclerView.Adapter

MyAdapter.class

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

  private Context context;
  private ArrayList<Student> students = new ArrayList<>();

  public MyAdapter(Context mContext, ArrayList<Student> mStudents) {
    this.context = mContext;
    this.students = mStudents;
  }

  @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View v = LayoutInflater.from(context).inflate(R.layout.item_row, parent, false);
    return new ViewHolder(v);
  }

  @Override public void onBindViewHolder(ViewHolder holder, int position) {

    final Student student = students.get(position);

    holder.name.setText(student.getName());
    holder.age.setText(student.getAge());

    holder.setClickListener(new ItemClickListener() {
      @Override public void onClickItem(int pos) {
        Toast.makeText(context, "CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
      }

      @Override public void onLongClickItem(int pos) {
        Toast.makeText(context, "LONG CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
      }
    });
  }

  @Override public int getItemCount() {
    return students.size();
  }

  public static class ViewHolder extends RecyclerView.ViewHolder
      implements View.OnClickListener, View.OnLongClickListener {

    private TextView name;
    private TextView age;
    private ItemClickListener mListener;

    public ViewHolder(View itemView) {

      super(itemView);
      name = (TextView) itemView.findViewById(R.id.tv_name);
      age = (TextView) itemView.findViewById(R.id.tv_age);

      itemView.setOnClickListener(this);
      itemView.setOnLongClickListener(this);
    }

    public void setClickListener(ItemClickListener listener) {
      this.mListener = listener;
    }

    @Override public void onClick(View view) {
      mListener.onClickItem(getLayoutPosition());
    }

    @Override public boolean onLongClick(View view) {
      mListener.onLongClickItem(getLayoutPosition());
      return true;
    }
  }

  public interface ItemClickListener {
    void onClickItem(int pos);

    void onLongClickItem(int pos);
  }
}

正如您在onBindViewHolder() 中看到的,我将onItemClickListener() 设置为持有人。

@Override public void onBindViewHolder(ViewHolder holder, int position) {

    final Student student = students.get(position);
    holder.name.setText(student.getName());
    holder.age.setText(student.getAge());

    holder.setClickListener(new ItemClickListener() {
      @Override public void onClickItem(int pos) {
        Toast.makeText(context, "CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
      }

      @Override public void onLongClickItem(int pos) {
        Toast.makeText(context, "LONG CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
      }
    });
  }

但我知道每次有新项目滚动到视图中时都会调用onBindViewHolder() 方法。所以在onBindViewHolder() 内部调用点击监听器会导致它内部的昂贵操作。

我该如何解决这个问题?

【问题讨论】:

  • 您不能在持有者对象本身上设置点击监听器。将其设置在包含的视图元素之一上。
  • 所以在onCreateViewHolder而不是onBindViewHolder中这样做

标签: android android-recyclerview onitemclicklistener


【解决方案1】:

您需要在ViewHolder 的视图上设置onClickListener(),即在您的情况下为itemView。一旦您单击完整视图,即根视图(在您的情况下为 itemView),它将立即调用 onClick() 方法

您还可以在根的孩子上设置onClickListener(),即姓名和年龄。

ViewHolder(View itemView) 构造函数内部:

itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(mContext,"clicked="+ getPosition(),Toast.LENGTH_SHORT).show();         

                }
            });

同样,您也可以致电onLongClickListner()name.setOnClickLisner() 在子视图中也是如此。

【讨论】:

  • 想知道为什么没有 onitemclick 列表器。 @Baqir,你的回答奏效了。
  • 请同时公开getPosition()方法的实现。你在 ViewHolder 构造函数中的位置如何
  • 如何获取那个位置的适配器数据?
  • getAdapterPosition() 将返回当前项目位置
【解决方案2】:

您可以为特定受众设置事件 Onclick:

例如:

 holder.layout.setClickListener(new ItemClickListener() {
  @Override public void onClickItem(int pos) {
    Toast.makeText(context, "CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
  }

【讨论】:

    【解决方案3】:

    您可以为父视图实现onClickListener,如下所示:

    //holder.view - parent layout inside recyclerView item
    holder.view.setTag(position);
    holder.view..setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = (int) v.getTag();
                Student student = students.get(pos);
                // Do your operation
    
            }
        });
    

    如果你想从 activity/fragment 中设置 onItemClickListener recyclerView 被初始化,你可以点击这个链接:http://www.littlerobots.nl/blog/Handle-Android-RecyclerView-Clicks/

    【讨论】:

      【解决方案4】:

      最简单的方法是在您的适配器中保存单个ItemClickListener

      public class WalletListRecyclerAdapter extends RecyclerView.Adapter<WalletListRecyclerAdapter.ViewHolder> {
          private List<Wallet> wallets;
          private ItemClickListener itemClickListener;
      
          @Override
          public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
              Wallet wallet = wallets.get(position);
      
              holder.root.setOnClickListener(v -> {
                  if (itemClickListener != null)
                      itemClickListener.onClick(holder.root, wallet);
              });
          }
      
          static class ViewHolder extends RecyclerView.ViewHolder {
              View root;
      
              public ViewHolder(View v) {
                  super(v);
                  root = v;
              }
          }
      
      
          public void setItemClickListener(ItemClickListener itemClickListener) {
              this.itemClickListener = itemClickListener;
          }
      
          public interface ItemClickListener {
              void onClick(View view, Wallet wallet);
          }
      }
      

      活动中:

      walletsAdapter = new WalletListRecyclerAdapter();
      walletsAdapter.setItemClickListener((view, wallet) -> {
          Intent intent = new Intent(this, WalletActivity.class);
          intent.putExtra(Const.KEY_WALLET, wallet);
          startActivity(intent);
      });
      

      【讨论】:

        【解决方案5】:

        替换此代码,

                @Override public void onBindViewHolder (ViewHolder holder,int position){
        
                    final Student student = students.get(position);
                    holder.name.setText(student.getName());
                    holder.age.setText(student.getAge());
        
        
                    holder.v.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(context, "CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
                        }
                    });
        
                    holder.v.setOnLongClickListener(new View.OnLongClickListener() {
                        @Override
                        public boolean onLongClick(View v) {
                            Toast.makeText(context, "CLICK : " + student.getName(), Toast.LENGTH_SHORT).show();
                            return false;
                        }
                    });
                }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-02
          相关资源
          最近更新 更多