How to set onClickListener on RecyclerView - java

I have a simple problem that I can't set onClickListener on recyclerview , i don't want to set onClickListener on items of recyclerview , just the recyclerview itself , I tried the ordinary way and it didn't work
( i tried to set an onClickListener on the parent Layout but the strange things it doesn't work because of the LinearLayoutManager that i set on recyclerview :| )
here's my code :
mRecyclerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("onClick","Clicked");
}
});
Adapter :
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private List<Message> mMessage;
public static class ViewHolder extends RecyclerView.ViewHolder{
private TextView txtSender;
private TextView txtMessage;
public ViewHolder(View v) {
super(v);
txtSender = (TextView) v.findViewById(R.id.txtSender);
txtMessage = (TextView) v.findViewById(R.id.txtText);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflatedView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recyclerview_item_row, parent, false);
return new ViewHolder(inflatedView);
}
public RecyclerAdapter(List<Message> messages) {
mMessage = messages;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message msg = mMessage.get(position);
holder.txtSender.setText(msg.getSender());
holder.txtMessage.setText(msg.getmessage());
}
#Override
public int getItemCount() {
return mMessage.size();
}

As per your need, you need to modify R.layout.recyclerview_item_row. Use a android LinearLayout put both of TextView(R.id.txtSender and R.id.txtText) inside that.
Modify your ViewHolder as below:
public static class ViewHolder extends RecyclerView.ViewHolder
{
private LinearLayout lvContainer;
private TextView txtSender;
private TextView txtMessage;
public ViewHolder(View v) {
super(v);
lvContainer = (LinearLayout) v.findViewById(R.id.lv_container); // R.id.lv_container this should be in your R.layout.recyclerview_item_row
txtSender = (TextView) v.findViewById(R.id.txtSender);
txtMessage = (TextView) v.findViewById(R.id.txtText);
}
}
Modify your onBindViewHolder as below
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Message msg = mMessage.get(position);
holder.txtSender.setText(msg.getSender());
holder.txtMessage.setText(msg.getmessage());
holder.lvContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Handle your click here
}
});
}

Related

How to get value from position adapter RecyclerView

I have 2 data items where the data has different id. When i click radio button then getting id by position.
Example : I have 2 data items, the first id is 57 and the second id is 59. When I click on the first data it must get a value of 57 or when I click on the second data it must get a value of 59.
private String convertAddressID;
private int previousSelected = -1;
private boolean isRadioChecked;
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
ModelGetAddress adapterAddress = modelGetAddressList.get(position);
convertAddressID = String.valueOf(adapterAddress.getId());
}
public class ViewHolder extends RecyclerView.ViewHolder {
private RadioButton radioButton;
public ViewHolder(#NonNull View itemView) {
super(itemView);
radioButton = itemView.findViewById(R.id.radioButton);
radioButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
previousSelected = getAdapterPosition();
notifyItemRangeChanged(0, modelGetAddressList.size());
Toast.makeText(getContext, convertAddressID, Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
ModelGetAddress adapterAddress = modelGetAddressList.get(position);
convertAddressID = String.valueOf(adapterAddress.getId());
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private RadioButton radioButton;
public ViewHolder(#NonNull View itemView) {
super(itemView);
radioButton = itemView.findViewById(R.id.radioButton);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
int position=getAdapterPosition();
Toast.makeText(conext, ""+modelGetAddressList.get(position).getId(), Toast.LENGTH_SHORT).show();
}
}
You can set the onClickListener in the onBindViewHolder where you always have the position. Call the findViewById in the ViewHolder class.
Try something like this my (untested) code:
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
((ViewHolder)holder).button.setOnClickListener(...)
}
public class ViewHolder extends RecyclerView.ViewHolder {
Button button;
ViewHolderContent(#NonNull View itemView) {
super(itemView);
button= itemView.findViewById(R.id.button);
}
}

How to add a recyclerview item dynamically when click a button in another activity?

I have a recyclerview in ShoppingCartActivity and a button in ProductDetailActivity. I want to send some data to ShoppingCartActivity when a button clicked in ProductDetailActivity and display them in recyclerview item that creates dynamically in ShoppingCartActivity.
I added addData method to recyclerview Adapter but it doesn't work and app crashes.
shop_btn = findViewById(R.id.add_to_shopping_cart);
shop_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent addToCart = new Intent(ProductDetailActivity.this, ShoppingCartActivity.class);
startActivity(addToCart);
}
});
//HERE IS MY RECYCLERVIEW ADAPTER
public class RecyclerViewAdapter_ShoppingCart extends RecyclerView.Adapter<RecyclerViewAdapter_ShoppingCart.MyViewHolder> {
private Context context;
List<CartItems> cartItemsList;
public RecyclerViewAdapter_ShoppingCart(Context context, List<CartItems> cartItemsList) {
this.context = context;
this.cartItemsList = cartItemsList;
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view;
LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.card_cart, parent, false);
return new MyViewHolder(view);
}
#NonNull
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.cart_title.setText(cartItemsList.get(position).getTitle());
holder.cart_price.setText(cartItemsList.get(position).getPrice());
Picasso.get().load(cartItemsList.get(position).getImageUrl()).into(holder.cart_img);
}
#Override
public int getItemCount() {
return cartItemsList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
TextView cart_title, cart_price;
ImageView cart_img;
public MyViewHolder(View itemView) {
super(itemView);
cart_title = itemView.findViewById(R.id.cart_title);
cart_price = itemView.findViewById(R.id.cart_price);
//cart_delete = itemView.findViewById(R.id.cart_delete);
cart_img = itemView.findViewById(R.id.cart_image);
}
}
public void addItem(List<CartItems> cartItems) {
CartItems newValue = new CartItems();
newValue.setTitle("123");
newValue.setPrice("123");
newValue.setImageUrl("");
cartItems.add(newValue);
notifyDataSetChanged();
}
}
My goal is adding recyclerview items dynamically to ShoppingCartActivity when a button clicked in ProductDetailActivity but app crashes.

viewHolder.getAdapterPosition() in adapter return -1 position and it caused IndexOutOfBoundException

i try to implement best practice to handle onclick in adapter, but i got problem IndexOutOfBoundException when getAdapterPostition inside onCreateViewHolder, whats wrong with my code?
i already try to check but not solve yet.
public class VideoAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private DataFrontVideo datas;
private Context context;
public VideoAdapter(DataFrontVideo datas, Context context) {
this.datas = datas;
this.context = context;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_video,null);
final ViewHolder viewHolder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DataVideo video = datas.getContent().get(viewHolder.getAdapterPosition()); // ERROR HERE
Intent intent = new Intent(context,DetailActivity.class);
intent.putExtra("datas",video);
context.startActivity(intent);
}
});
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int position) {
DataVideo dataVideo = datas.getContent().get(position);
ViewHolder vh = (ViewHolder)viewHolder;
vh.tvTitle.setText(dataVideo.getJudul());
vh.tvArtis.setText(dataVideo.getAlias());
vh.tvPrice.setText((dataVideo.getPrice().equals("0")?"Gratis":dataVideo.getPrice()));
Glide.with(vh.img.getContext()).load(dataVideo.getThumb_pic()).into(vh.img);
}
#Override
public int getItemCount() {
return (datas == null)? 0 : datas.getContent().size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private ImageView img;
private TextView tvTitle,tvArtis,tvPrice;
public ViewHolder(#NonNull View itemView) {
super(itemView);
img = itemView.findViewById(R.id.imgVideo);
tvArtis = itemView.findViewById(R.id.tvartis);
tvTitle = itemView.findViewById(R.id.tvTitle);
tvPrice = itemView.findViewById(R.id.tvPrice);
}
}
}
it should not return -1
Inside your ViewHolder you need to apply the setOnClickListener and get the item position on click by using the getAdapterPosition() like below
public class ViewHolder extends RecyclerView.ViewHolder{
private ImageView img;
private TextView tvTitle,tvArtis,tvPrice;
public ViewHolder(#NonNull View itemView) {
super(itemView);
img = itemView.findViewById(R.id.imgVideo);
tvArtis = itemView.findViewById(R.id.tvartis);
tvTitle = itemView.findViewById(R.id.tvTitle);
tvPrice = itemView.findViewById(R.id.tvPrice);
YOUR_VIEW.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(mContext,"Position==>> "+getAdapterPosition(),Toast.LENGTH_LONG).show();
DataVideo video = datas.getContent().get(viewHolder.getAdapterPosition()); // ERROR HERE
Intent intent = new Intent(context,DetailActivity.class);
intent.putExtra("datas",video);
context.startActivity(intent);
}
});
}
}
Actually, the problem just because you are registering click listener in your onCreateViewHolder which is wrong you need to register on Click listener in your onBindViewHolder like bellow
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int position) {
DataVideo dataVideo = datas.getContent().get(position);
ViewHolder vh = (ViewHolder)viewHolder;
vh.tvTitle.setText(dataVideo.getJudul());
vh.tvArtis.setText(dataVideo.getAlias());
vh.tvPrice.setText((dataVideo.getPrice().equals("0")?"Gratis":dataVideo.getPrice()));
Glide.with(vh.img.getContext()).load(dataVideo.getThumb_pic()).into(vh.img);
vh.parentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context,DetailActivity.class);
intent.putExtra("datas",dataVideo);
context.startActivity(intent);
}
});
}
Move your click in onBindViewHolder .Here it will work for title click ,if you want all click make viewholder complete layout and implement click listener
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder viewHolder, int position) {
DataVideo dataVideo = datas.getContent().get(position);
ViewHolder vh = (ViewHolder)viewHolder;
vh.tvTitle.setText(dataVideo.getJudul());
vh.tvArtis.setText(dataVideo.getAlias());
vh.tvPrice.setText((dataVideo.getPrice().equals("0")?"Gratis":dataVideo.getPrice()));
Glide.with(vh.img.getContext()).load(dataVideo.getThumb_pic()).into(vh.img);
vh.tvTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context,DetailActivity.class);
intent.putExtra("datas",dataVideo );
context.startActivity(intent);
}
});
}

How to change image of imageView from drawable inside an adapter of RecyclerView after an item has been clicked?

I fetched data from SERVER to populate RECYCLER view
I have an imageview in each recyclerview row
When I click that imageview, I want to load my drawable into the imageview
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Drawable placeholder = holder.imageView.getContext().getResources().getDrawable(R.drawable.app);
holder.imageView.setImageDrawable(placeholder);
}
});
The above is what I tried but it says "holder" needs to be declared final but in reality, I haven't even mentioned it in a way I could write "final holder" or whatever.
My ADAPTER code :
public class ProductsAdapter extends
RecyclerView.Adapter<ProductsAdapter.ProductViewHolder> {
private Context mCtx;
private List<Product> productList;
public ProductsAdapter(Context mCtx, List<Product> productList) {
this.mCtx = mCtx;
this.productList = productList;
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.product_list, null);
return new ProductViewHolder(view);
}
#Override
public void onBindViewHolder(ProductViewHolder holder, int position) {
final Product product = productList.get(position);
//loading the image
Glide.with(mCtx)
.load(product.getImage())
.into(holder.imageView);
holder.textViewTitle.setText(product.getTitle());
holder.textViewShortDesc.setText(product.getShortdesc());
holder.textViewRating.setText(String.valueOf(product.getRating()));
holder.textViewPrice.setText(String.valueOf(product.getPrice()));
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Drawable placeholder = holder.imageView.getContext().getResources().getDrawable(R.drawable.app);
holder.imageView.setImageDrawable(placeholder);
}
});
}
#Override
public int getItemCount() {
return productList.size();
}
class ProductViewHolder extends RecyclerView.ViewHolder {
TextView textViewTitle, textViewShortDesc, textViewRating, textViewPrice;
ImageView imageView;
public ProductViewHolder(View itemView) {
super(itemView);
textViewTitle = itemView.findViewById(R.id.textViewTitle);
textViewShortDesc = itemView.findViewById(R.id.textViewShortDesc);
textViewRating = itemView.findViewById(R.id.textViewRating);
textViewPrice = itemView.findViewById(R.id.textViewPrice);
imageView = itemView.findViewById(R.id.imageView);
}
}
}
You can declare the holder final in the method header
public void onBindViewHolder(final ProductViewHolder holder, int position) {
Your code here
}
There are several solutions:
1) Make your holder to be final doing
#Override
public void onBindViewHolder(final ProductViewHolder holder, int position)
or using additional variable
final Holder finalHolder = holder;
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Drawable placeholder = finalHolder.imageView.getContext().getResources().getDrawable(R.drawable.app);
holder.imageView.setImageDrawable(placeholder);
}
});
2) When you set ClickListener on particular view, you are sure that only that view will trigger action, so you can use that knowledge
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ImageView imgView = (ImageView) view;
Drawable placeholder = imgView.getContext().getResources().getDrawable(R.drawable.app);
imgView.setImageDrawable(placeholder);
}
});
If you're using View Binding in kotlin then it will work,
holder.binding.imageView.setImageDrawable(ContextCompat.getDrawable(holder.binding.imageView.context,R.drawable.medal_2)
without view binding it will be
holder.imageView.setImageDrawable(ContextCompat.getDrawable(holder.imageView.context,R.drawable.medal_2)

Interaction between the recyclerview

there are two recyclerview and two adapters. Both recyclerview contain text fields and buttons. I have below pressing in one recyclerview item jumped to another recyclerview and vice versa. How to do it?
First adapter:
public class RVAdapterStart extends RecyclerView.Adapter<RVAdapterStart.TaskViewHolder> {
public static class TaskViewHolder extends RecyclerView.ViewHolder {
RelativeLayout relativeLayout;
private TextView title;
private TextView status;
private Button button;
TaskViewHolder(View view) {
super(view);
relativeLayout = (RelativeLayout) view.findViewById(R.id.frameLayout);
title = (TextView) view.findViewById(R.id.title);
status = (TextView) view.findViewById(R.id.status);
button = (Button) view.findViewById(R.id.tasks_finish);
}
}
private List<Task> tasksStart;
RVAdapterStart() {
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public void onBindViewHolder(TaskViewHolder holder, final int position) {
holder.title.setText(tasksStart.get(position).getTitle());
holder.status.setText(tasksStart.get(position).getStatus());
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public int getItemCount() {
return tasksStart.size();
}
#Override
public TaskViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_tasks_start, viewGroup, false);
TaskViewHolder tvh = new TaskViewHolder(view);
return tvh;
}
Second adapter:
public class RVAdapterProcces extends RecyclerView.Adapter<RVAdapterProcces.TasksViewHolder> {
public static class TasksViewHolder extends RecyclerView.ViewHolder {
RelativeLayout relativeLayout;
private TextView title;
private TextView status;
private Button TaskFinishBtn;
private Button TaskCancelBtn;
TasksViewHolder(View view) {
super(view);
relativeLayout = (RelativeLayout) view.findViewById(R.id.relative_tasks_procces);
title = (TextView) view.findViewById(R.id.title_procces);
status = (TextView) view.findViewById(R.id.status_procces);
TaskFinishBtn = (Button) view.findViewById(R.id.tasks_finish);
TaskCancelBtn = (Button) view.findViewById(R.id.tasks_procces_cancel);
}
}
private List<Task> tasksProcces = new ArrayList<Task>();
RVAdapterProcces() {
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
#Override
public void onBindViewHolder(TasksViewHolder holder, final int position) {
holder.title.setText(tasksProcces.get(position).getTitle());
holder.status.setText(tasksProcces.get(position).getStatus());
}
#Override
public int getItemCount() {
return tasksProcces.size();
}
#Override
public TasksViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_tasks_procces, viewGroup, false);
TasksViewHolder tvh = new TasksViewHolder(view);
return tvh;
}

Categories