Skip to content

Instantly share code, notes, and snippets.

@redleafar
Created September 14, 2016 22:30
Show Gist options
  • Save redleafar/fcd93746f7fc0f0dc6d9126eea523b72 to your computer and use it in GitHub Desktop.
Save redleafar/fcd93746f7fc0f0dc6d9126eea523b72 to your computer and use it in GitHub Desktop.
Set a click listener on a RecyclerView

Source: http://antonioleiva.com/recyclerview-listener/

If you’ve used a RecyclerView, you may know that they don’t have a setOnItemClickListener as ListView had, so we have to create our own way to do it. Many people asked me how to do this, so that’s why I decided to write about it. There are many ways to achieve this, but I will show you the way I usually do it. My mechanism consists of passing the listener as a parameter to the constructor and then assign it when I bind the data to the view in onBindViewHolder. You’ll first need an interface that specifies listener’s behaviour. In this example, there is a sample model called ContentItem, so the click will return an item of that type:

public interface OnItemClickListener {
    void onItemClick(ContentItem item);
}

The constructor will receive an object that implements this interface, along with the items to be rendered:

private final List<ContentItem> items;
private final OnItemClickListener listener;

public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
    this.items = items;
    this.listener = listener;
}

You could alternatively create a setOnItemClickListener method and assign it that way. Now, in onBindViewHolder the ViewHolder will receive the constructor in the custom bind method:

@Override public void onBindViewHolder(ViewHolder holder, int position) {
    holder.bind(items.get(position), listener);
}

This is how this bind method looks (this goes inside the ViewHolder class which is inside the adapter):

public void bind(final ContentItem item, final OnItemClickListener listener) {
    ...
    itemView.setOnClickListener(new View.OnClickListener() {
        @Override public void onClick(View v) {
            listener.onItemClick(item);
        }
    });
}

Use it whenever you need it by creating a new adapter and the listener that will implement the behaviour when an item is clicked. A simple example:

recycler.setAdapter(new ContentAdapter(items, new ContentAdapter.OnItemClickListener() {
    @Override public void onItemClick(ContentItem item) {
        Toast.makeText(getContext(), "Item Clicked", Toast.LENGTH_LONG).show();
    }
}));

Take a look at the whole code of this adapter. Of course there are many alternatives here. In the end, the implementation is left to the developer when using RecyclerView, so choose whatever fits better in your situation.

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

    public interface OnItemClickListener {
        void onItemClick(ContentItem item);
    }

    private final List<ContentItem> items;
    private final OnItemClickListener listener;

    public ContentAdapter(List<ContentItem> items, OnItemClickListener listener) {
        this.items = items;
        this.listener = listener;
    }

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

    @Override public void onBindViewHolder(ViewHolder holder, int position) {
        holder.bind(items.get(position), listener);
    }

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

    static class ViewHolder extends RecyclerView.ViewHolder {

        private TextView name;
        private ImageView image;

        public ViewHolder(View itemView) {
            super(itemView);
            name = (TextView) itemView.findViewById(R.id.name);
            image = (ImageView) itemView.findViewById(R.id.image);
        }

        public void bind(final ContentItem item, final OnItemClickListener listener) {
            name.setText(item.name);
            Picasso.with(itemView.getContext()).load(item.imageUrl).into(image);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override public void onClick(View v) {
                    listener.onItemClick(item);
                }
            });
        }
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment