8

I have an ImageView in CardViews of my RecyclerView. I would like to catch the onClick on the ImageView, like I already did with the ListView. So, in the public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) I tried with:

 myViewHolder.imageView.setClickable(true);
 myViewHolder.imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
               Log.d("TEST", "Clicked");
            }

but this was totally ignored. The following code is working:

 myViewHolder.imageView.setImageResource(R.drawable.star_yellow);

What can I do?

Vipul Asri
  • 8,903
  • 3
  • 46
  • 71
helloimyourmind
  • 994
  • 4
  • 14
  • 30
  • Can you please post your xm and, perhaps, onBindViewHolder and ViewHolder itselfl? I have one project with ImageViews inside CardView and onClick works just fine. – Kistamushken Oct 21 '15 at 16:07
  • http://stackoverflow.com/questions/28379302/add-clicklistner-for-button-inside-a-cardview-populated-using-a-recyclerview if this is not working post your layout also – Pavan Oct 21 '15 at 16:40

2 Answers2

19

Here's what I do in my project.

  1. Have an interface class somewhere in your project:

    public interface RecyclerViewClickListener {
    
        void onRowClicked(int position);
        void onViewClicked(View v, int position);
    }
    
  2. In your RecyclerView.Adapter class, add this interface as a field and pass it to adapter via constructor:

    public class YourRecAdapter extends RecyclerView.Adapter<YourRecAdapter.SimpleViewHolder>{
    
        private RecyclerViewClickListener listener;
    
        public YourRecAdapter(RecyclerViewClickListener listener){
            this.listener = listener;
        }
    
        public static class SimpleViewHolder extends RecyclerView.ViewHolder {
    
            public SimpleViewHolder(View itemView, final RecyclerViewClickListener listener) {
                super(itemView);
    
                // find view ids here
    
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(listener != null)
                            listener.onRowClicked(getAdapterPosition());
                    }
                });
    
                someViewholderView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if(listener != null)
                            listener.onViewClicked(v, getAdapterPosition());
                    }
                });
            }
        }
    }
    
  3. Implement the interface in your Activity / Fragment:

    public class YourFragment extends Fragment implements RecyclerViewClickListener {
    
       @Override
       public void onViewClicked(View v, int position) {
           if(v.getId == R.id.yourDesiredView){
               // Do your stuff here
           }
       }
    
       @Override
       public void onRowClicked(int position) {
           // Clicked entire row
       }
    }
    
Tomislav Turcic
  • 879
  • 1
  • 11
  • 24
  • Thank you for the reply, but isn't possible to manage the click in the onBindViewHolder method? – helloimyourmind Oct 21 '15 at 16:33
  • Yes, just move all my .setOnClickListener(...) stuff to onBindViewHolder() method. Then you don't have to pass listener to your ViewHolder's constructor. However, I think it's slightly more efficient to have onClick methods in your ViewHolder, otherwise they get recreated all the time as you scroll through list. – Tomislav Turcic Oct 21 '15 at 16:37
  • In MyFragment I've to create a new object of RecyclerViewClickListener type and pass it as parameter in the Adapter constructor? – helloimyourmind Oct 21 '15 at 17:10
  • Yes, just pass 'this' as parameter and let your Fragment implement the interface. Add any other parameters to your adapter as needed (data, context, etc). – Tomislav Turcic Oct 21 '15 at 17:33
  • Hi @Tomislav. I'm trying to do that your are explain here, but I can call the interface from my fragment. I've open a post about this (http://stackoverflow.com/questions/38954507/my-interface-class-dont-work-when-i-call-it-from-a-fragment) Can you take a look to see what's the problem, please??? – S.P. Aug 15 '16 at 11:50
  • Hey, this answer is pretty old but maybe you can answer my question: in onViewItemClicked you pass the View to query it in the implementation in the Activity. But you have to set that listener on multiple Views for that to make sense, right? What i mean is, "someViewHolderView" represents one single View and you have to set that onClickListener on multiple different Views to query for the ID? – Florian Walther Oct 19 '17 at 02:13
0

Inside your Viewholder class you can set the OnClickListener but you will need another interface in order to pass your OnClick register back to your adapter (or wherever your intended target is).

Devsil
  • 598
  • 3
  • 16
  • Sorry. It depends on what you are trying to do with the OnClick. If you are doing something that could be done locally inside the ViewHolder itself (like just resize the image) you wouldnt need an interface or any other method of passing the OnClick back to the adapter. However, if you are trying to save move to a new activity or switch to an image that the ViewHolder does not have a reference to you will need a custom listener (an interface) that the ViewHolder has a reference to that then the owning activity or adapter can listen for. – Devsil Oct 21 '15 at 16:19
  • I need to do the operations in the onBindViewHolder – helloimyourmind Oct 21 '15 at 16:27