RecyclerView OnClick not working
Asked Answered
G

3

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.

Grane answered 23/2, 2016 at 17:46 Comment(4)
Is it not firing at all or is it just firing incorrectly. You should be setting the onClick during the bindViewHolder() since you only create the view holder once initially and then "recycle" it when the list is scrolled.Wolves
@Wolves its not at all firing.Grane
Is the background of the view unset? also add a toast for debug.Wolves
see this https://mcmap.net/q/49516/-why-doesn-39-t-recyclerview-have-onitemclicklistenerGearing
H
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.

Hyperaesthesia answered 23/2, 2016 at 18:10 Comment(9)
hey I have used just the same method up there, and its not working.Grane
that is why i was typing out the other way my prefered way :), try this out @AkshayBhasinHyperaesthesia
what is this rlContainer?Grane
it is basically a container of the viewHolder... ie:<RelativeLayout><TextView><ImageView></RelativeLayout>.....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.Hyperaesthesia
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!Grane
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.Hyperaesthesia
@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);Plenary
What is User user = users.getPosition();Ezmeralda
@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.)Hyperaesthesia
L
2

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

You’re done Should work.

Limiting answered 23/2, 2016 at 17:46 Comment(0)
A
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);
}
Aubrey answered 23/2, 2016 at 18:2 Comment(3)
Doesn't work. Now i can't even see the onClick effect on the items.Grane
Show code for the MainActivity where you set your AdapterAubrey
hey why did you pass the itemClickListener to the adapter? Its giving an error.Grane

© 2022 - 2024 — McMap. All rights reserved.