How to add OnClickListner to CardView?

2020-06-05 07:47发布

问题:

I am working with RecyclerView and CardView. I want to attach OnClickListner to each card. I tried with many answers available on stackoverflow, but they are not working for me. So far I have tried -

public class SubjectAdapter extends RecyclerView.Adapter<SubjectAdapter.ViewHolder> implements View.OnClickListener,
    View.OnLongClickListener{

private static final String LOGCAT = "SubjectAdapter";
private final Context mContext;

List<Subject> SubjectsList;

public SubjectAdapter(Context context) {
    super();
    this.mContext = context;
    SQLiteDatabase.loadLibs(mContext);
    DBHelper myDbHelper = new DBHelper(mContext);
    SubjectsList = new ArrayList<Subject>();
    SubjectsList = myDbHelper.getAllSubjects();
    myDbHelper.close();
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View v = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.subject_cardview_row, viewGroup, false);
    ViewHolder viewHolder = new ViewHolder(v);

    // Below two lines are NOT working
    viewHolder.tvSubjectName.setOnClickListener(this);
    //viewHolder.setOnClickListener(this);

    return viewHolder;
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
    Subject subject = SubjectsList.get(i);
    viewHolder.tvSubjectName.setText(subject.getSubject_Name());
    viewHolder.tvCounts.setText(String.valueOf(subject.getSubject_Number_of_Questions()));

    // Below two lines are NOT working
    viewHolder.tvSubjectName.setOnClickListener(this);
    //viewHolder.setOnClickListener(this);
}

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

@Override
public void onClick(View v) {
    // It's not working either
    ViewHolder holder = (ViewHolder) v.getTag();
    int position = holder.getPosition();

    if (v.getId() == holder.tvSubjectName.getId()){
        Log.d(LOGCAT, "tvSubjectName onClick at" + position);
        //Toast.makeText(mContext, "tvSubjectName onClick at" + position, Toast.LENGTH_LONG).show();
    } else {
        Log.d(LOGCAT, "RecyclerView Item onClick at " + position);
        //Toast.makeText(mContext, "RecyclerView Item onClick at " + position, Toast.LENGTH_LONG).show();
    }
}

@Override
public boolean onLongClick(View v) {
    return false;
}

class ViewHolder extends RecyclerView.ViewHolder {

    public TextView tvSubjectName;
    public TextView tvCounts;

    public ViewHolder(View itemView) {
        super(itemView);
        tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
        tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);
    }
}
}

As one can see, I have tried setOnClickListener with both onCreateViewHolder and onBindViewHolder, also as separate onClick, but none of them seems to be working for me. So, I want to know, How to add OnClickListner to CardView?

回答1:

View returned by onClick does not necessarily correspond to View row hierarchy of the recycler view. I think you should modify onBindViewHolder with

@Override
public void onBindViewHolder(final ViewHolder viewHolder, final int i) {
   final Subject subject = SubjectsList.get(i); 
   viewHolder.tvSubjectName.setOnClickListener(new View.OnClickListener(){


    @Override
    public void onClick(View v) {
        Log.d(LOGCAT, "tvSubjectName onClick at" + i);
       // etc
    }

   });
...
}

If you use long click then replace View.OnClickListener with View.OnLongClickListener and onClick with onLongClick.



回答2:

This worked for me ! Put the setOnClickListener-method inside the constructor of your ViewHolder class.

class ViewHolder extends RecyclerView.ViewHolder
{
    public TextView tvSubjectName;
    public TextView tvCounts;

    public ViewHolder(View itemView) 
    {
        super(itemView);
        tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
        tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);

        itemView.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                 //write here the code for wathever you want to do with a card
                 //...
            }
        });

}

}



回答3:

Check out Lucas Rocha's new TwoWayView API.

TwoWayLayoutManager is a simple API on top of LayoutManager that does all the laborious work for you so that you can focus on how the child views are measured, placed, and detached from the RecyclerView.

Follow his site and implementation of the API is relatively simple and might help you through some of the difficult complexities RecyclerView and CardView pose.

http://lucasr.org/2014/07/31/the-new-twowayview/



回答4:

Set OnClickListener to itemView in RecyclerView.ViewHolder constructor, also you can fetch position of cardView using getAdapterPosition() method which can help you to pass the data to new activity using putExtra method of intent. doc for getAdapterPosition method

`

class ViewHolder extends RecyclerView.ViewHolder
{
    public TextView tvSubjectName;
    public TextView tvCounts;

    public ViewHolder(View itemView) 
    {
        super(itemView);
        tvSubjectName = (TextView) itemView.findViewById(R.id.tv_subject_name);
        tvCounts = (TextView) itemView.findViewById(R.id.tv_text_counts);

        itemView.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                 int position = getAdapterPosition();
                 // use position to put extra data
            }
        });
}

`



回答5:

If you really want to implement onclick listener then do the following

  1. add a View object in your ViewHolderClass and initialize it to the itemView recieved in the constructor

2.setOnClickListener to the view object you declared(in ViewHolder) onBindViewHolder in the Adapter class

this will work for the entire cardView