7

I have made a horizontal recyclerview inside a fragment. Now when I click on any item I don't see the on click listener working. Here is my code for the Adapter class:

public class FeaturedProductsAdapter  extends RecyclerView.Adapter<FeaturedProductsAdapter.CustomViewHolder> {
private List<FeaturedProductInfo> feedItemList;
private Context mContext;

public FeaturedProductsAdapter(Context context, List<FeaturedProductInfo> feedItemList) {
    this.feedItemList = feedItemList;
    this.mContext = context;
}
public class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    protected ImageView imageView;
    protected TextView textView,priceView;
    private Context context;


    public CustomViewHolder(View view,Context context) {

        super(view);
        this.context=context;
        this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
        this.textView = (TextView) view.findViewById(R.id.prodTitle);
        this.priceView = (TextView) view.findViewById(R.id.prodPrice);
        view.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {

        int position = getLayoutPosition(); // gets item position
        Log.e("Check", position + "");
        FeaturedProductInfo user = feedItemList.get(position);//[position];
        // We can access the data within the views
        Intent intent = new Intent(context, ProductDescription.class);
        intent.putExtra("id", user.getId());
        mContext.startActivity(intent);


    }

}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.featured_product_list_item_card, null);
    Context context = viewGroup.getContext();

    CustomViewHolder viewHolder = new CustomViewHolder(view,context);

    return viewHolder;
}

@Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
    FeaturedProductInfo feedItem = feedItemList.get(i);

    //Download image using picasso library
    if(!feedItem.getUrl().contains("."))
    {
        feedItem.setUrl("nothing");
    }
    Picasso.with(mContext).load(feedItem.getUrl())
            .error(R.drawable.unavailable)
            .placeholder(R.drawable.unavailable)
            .resize(110,110)
            .into(customViewHolder.imageView);

    //Setting text view title
    customViewHolder.textView.setText(feedItem.getTitle());
    customViewHolder.priceView.setText(feedItem.getPrice());
    //Log.e("Featured: ","SET");
}

@Override
public int getItemCount() {
    return (null != feedItemList ? feedItemList.size() : 0);
}

}

I think I am not getting how to use the view holder properly. While I have used the same code for recyclerView in another activities and it works like charm.

Akshay Bhasin
  • 167
  • 2
  • 3
  • 11

3 Answers3

18

1.Simple Click Handler within ViewHolder

RecyclerView does not have special provisions for attaching click handlers to items unlike ListView which has the method setOnItemClickListener(). To achieve a similar effect, we can attach click events within the ViewHolder within our adapter:

public class ContactsAdapter extends RecyclerView.Adapter<ContactsAdapter.ViewHolder> {
    // ...

    // Used to cache the views within the item layout for fast access
    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
        public TextView tvName;
        public TextView tvHometown;
        private Context context;

        public ViewHolder(Context context, View itemView) {
            super(itemView);
            this.tvName = (TextView) itemView.findViewById(R.id.tvName);
            this.tvHometown = (TextView) itemView.findViewById(R.id.tvHometown);
            // Store the context
            this.context = context;
            // Attach a click listener to the entire row view
            itemView.setOnClickListener(this);
        }

        // Handles the row being being clicked
        @Override
        public void onClick(View view) {
            int position = getLayoutPosition(); // gets item position
            User user = users.get(position);
            // We can access the data within the views
            Toast.makeText(context, tvName.getText(), Toast.LENGTH_SHORT).show();
        }
    }

    // ...
}

Another way is my preferred way.. but this is also a fine way to go about it.

My onBindViewHolder

@Override
    public void onBindViewHolder(CategoryViewHolder holder, int position) {
        Category category = mCategories.get(position);

        holder.tvTitle.setText(category.getTitle());
        holder.tvDescription.setText(category.getDescription());

        holder.rlContainer.setOnClickListener(mClickListener);
        holder.rlContainer.setTag(holder);
    }

My class level (Adapter object of View.OnClickListner)

View.OnClickListener mClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            CategoryViewHolder holder = (CategoryViewHolder) view.getTag();
            int position = holder.getAdapterPosition();

            startAppointmentBookingFor(mCategories.get(position));
        }
    };

so basically attach the listener to any view in your holder (I try to put it on container only), then extract it out on the onclick and handle positions etc.

Tom11
  • 2,419
  • 8
  • 30
  • 56
yUdoDis
  • 1,098
  • 6
  • 15
  • hey I have used just the same method up there, and its not working. – Akshay Bhasin Feb 23 '16 at 18:14
  • that is why i was typing out the other way my prefered way :), try this out @AkshayBhasin – yUdoDis Feb 23 '16 at 18:17
  • what is this rlContainer? – Akshay Bhasin Feb 23 '16 at 18:27
  • it is basically a container of the viewHolder... ie:.....so i just attached an id and voila the parent becomes my container for the view which is used by my adapter, you can for now just attach that to your priceView or TextView. – yUdoDis Feb 23 '16 at 18:28
  • thanks, your method for onBindViewHolder worked for me. But I can't figure out why the basic onClickListener is not working. Anyways thanks a lot! – Akshay Bhasin Feb 24 '16 at 15:43
  • it should work, its probably something trivial which youre missing...both ways work, there is a third way too, but nvm that, the trick to recycler view is duh..views ie viewholders get recycled, hence i just reattach whatever i need during onBind simpler that way...anywho youre welcome, happy coding. – yUdoDis Feb 24 '16 at 18:02
  • 4
    @AkshayBhasin I'm quite sure that you must have forgotten to attach the click listener. This is the line you must have missed this line: itemView.setOnClickListener(this); – iamlegend Jul 25 '16 at 15:05
  • What is `User user = users.getPosition();` – Onur-Andros Ozbek Jul 31 '17 at 21:38
  • @OnurOzbek User is the list object which my recycler view adapter uses. so basically, my view holder also has a user object (my recycler view renders a list of users.) – yUdoDis Aug 03 '17 at 07:04
2

In ‘CustomViewHolder’ below ‘super(view)’ add view.setOnClickListener(this)

You’re done Should work.

James Christian Kaguo
  • 1,251
  • 15
  • 14
1

Make the following changes to your Adapter:

public class FeaturedProductsAdapter  extends RecyclerView.Adapter<FeaturedProductsAdapter.CustomViewHolder> {
private List<FeaturedProductInfo> feedItemList;
private Context mContext;
private OnItemClickListener onItemClickListener;

public FeaturedProductsAdapter(Context context, List<FeaturedProductInfo,OnItemClickListener onItemClickListener> feedItemList) {
    this.feedItemList = feedItemList;
    this.mContext = context;
    this.onItemClickListener = onItemClickListener;

}
public class CustomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    protected ImageView imageView;
    protected TextView textView,priceView;
    private Context context;


    public CustomViewHolder(View view,Context context) {

        super(view);
        this.context=context;
        this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
        this.textView = (TextView) view.findViewById(R.id.prodTitle);
        this.priceView = (TextView) view.findViewById(R.id.prodPrice);
        view.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {

        onItemClickListener.onItemClick(getLayoutPosition());
        Log.e("Check", position + "");
        FeaturedProductInfo user = feedItemList.get(position);//[position];
        // We can access the data within the views
        Intent intent = new Intent(context, ProductDescription.class);
        intent.putExtra("id", user.getId());
        mContext.startActivity(intent);


    }

}

public interface OnItemClickListener{
    void onItemClick(int position);
}

@Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.featured_product_list_item_card, null);
    Context context = viewGroup.getContext();

    CustomViewHolder viewHolder = new CustomViewHolder(view,context);

    return viewHolder;
}

@Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
    FeaturedProductInfo feedItem = feedItemList.get(i);

    //Download image using picasso library
    if(!feedItem.getUrl().contains("."))
    {
        feedItem.setUrl("nothing");
    }
    Picasso.with(mContext).load(feedItem.getUrl())
            .error(R.drawable.unavailable)
            .placeholder(R.drawable.unavailable)
            .resize(110,110)
            .into(customViewHolder.imageView);

    //Setting text view title
    customViewHolder.textView.setText(feedItem.getTitle());
    customViewHolder.priceView.setText(feedItem.getPrice());
    //Log.e("Featured: ","SET");
}

@Override
public int getItemCount() {
    return (null != feedItemList ? feedItemList.size() : 0);
}
Veeresh Charantimath
  • 4,641
  • 5
  • 27
  • 36