Imagine a CardView with a button and text field. When I press on a button, text should change in the textfield. Code for my recyclerView is given below, where I am setting the text and a listener for a button:
#Override
public void onBindViewHolder(CategoriesDetailedViewHolder holder, int position) {
final CategoryDetailedModel model = categoriesDetailedModels.get(position);
holder.description.setText(model.getQuestion());
holder.btnPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
holder.description.setText("some text");
}
});
}
The main problem is with the string:
holder.description.setText("some text");
It cannot be accessed from an inner class.
Is anyone have any idea how to change text in card view from itself.
Update 1
public class CategoriesDetailedViewHolder extends RecyclerView.ViewHolder{
CardView cv;
TextView description;
TextView positiveCounter;
TextView negativeCounter;
TextView btnPlus;
View negativeCounterWrapper;
View positiveCounterWrapper;
CategoriesDetailedViewHolder(View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cv);
description = (TextView)itemView.findViewById(R.id.main_text);
positiveCounter = (TextView)itemView.findViewById(R.id.tv_positive_count_in_circle);
negativeCounter = (TextView)itemView.findViewById(R.id.tv_negative_count_in_circle);
btnPlus = (TextView)itemView.findViewById(R.id.plus_button);
positiveCounterWrapper = itemView.findViewById(R.id.positive_count_wrapper);
negativeCounterWrapper = itemView.findViewById(R.id.negative_count_wrapper);
cv.setPreventCornerOverlap(false);
}
}
#Override
public CategoriesDetailedViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categories_detailed_list_row_view, parent, false);
CategoriesDetailedViewHolder pvh = new CategoriesDetailedViewHolder(v);
context = parent.getContext();
return pvh;
}
Instead of,
TextView description;
Make it,
public TextView description;
EDIT:
Change the following,
#Override
public void onBindViewHolder(CategoriesDetailedViewHolder holder, int position) { ... }
to,
#Override
public void onBindViewHolder( final CategoriesDetailedViewHolder holder, int position) { .... }
I use this code and it works fine, you just need to use onBind method.
This is one example, I use this in my project and you can just change it to suit your needs:
public void onBindViewHolder(final TipsViewHolder TipsViewHolder, final int i) {
TipsViewHolder.cardText.setText("Old text");
TipsViewHolder.txtBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TipsViewHolder.cardText.setText("New Text");
}
});
}
Related
I have a simple RecyclerView with an Interface that is linked to the activity. The Issue is the items in the recyclerView need double click in order to perform an action.
This is the AllProductsAdapter Code :
public class AllProductsAdapter extends RecyclerView.Adapter<AllProductsAdapter.ViewHolder> {
RecyclerViewClickInterfaceNew recyclerViewClickInterface;
List<ProductsModel> productsModelList;
Context context;
public AllProductsAdapter(List<ProductsModel> productsModelList, Context context, RecyclerViewClickInterfaceNew recyclerViewClickInterface) {
this.productsModelList = productsModelList;
this.context = context;
this.recyclerViewClickInterface = recyclerViewClickInterface;
}
#NonNull
#Override
public AllProductsAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.product_items, parent, false);
return new AllProductsAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull AllProductsAdapter.ViewHolder holder, int position) {
ProductsModel productsModel = productsModelList.get(position);
PicassoTrustAll.getInstance(context)
.load(productsModel.getProduct_image())
.into(holder.catImage);
}
#Override
public int getItemCount() {
return productsModelList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView catImage;
TextView catName;
CardView categoryCard;
public ViewHolder(#NonNull View itemView) {
super(itemView);
catImage = itemView.findViewById(R.id.catImage);
catName = itemView.findViewById(R.id.catName);
categoryCard = itemView.findViewById(R.id.categoryCard);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (recyclerViewClickInterface != null)
recyclerViewClickInterface.onItemClick(v, getAdapterPosition());
}
});
}
}
This is my RecyclerViewClickInterfaceNew :
public interface RecyclerViewClickInterfaceNew {
void onItemClick(View view , int position);
void onLongItemClick(int position);
}
This is my MainActivity code :
#Override
public void onItemClick(View view , int position) {
ImageView img= view.findViewById(R.id.catImage);
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(AllProductsList.this, "Imgclciked", Toast.LENGTH_SHORT).show();
}
});
}
Here in the MainActivity, the Toast shows after clicking 2 times on the Image. How can i fix it to a normal single click ? Please let me know your answer.
From this code
#Override
public void onItemClick(View view , int position) {
//when different item is FIRST clicked, a new instance of catImage is produced
ImageView img= view.findViewById(R.id.catImage);
//the img onClick is set here to require a second click
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(AllProductsList.this, "Imgclciked", Toast.LENGTH_SHORT).show();
}
});
}
For each new item on the Recycler View, you reset the click handling.
I'll suggest you set the onClickListener ON the ViewHolder. It's not the best practice but it'll suffice for your code
I think that's because of you are using NestedScrollView ,
you should add this line to your recyclerview
android:nestedScrollingEnabled="false"
Why am I getting random result on item click? My error is inside the btn onClick Listener but what shows in my TextView (reference_number) is fine. when button clicked - it will open another activity to show more details about it but it shows random result, after I scroll my recyclerView it will change the result again. ## im confused already, below is all the codes inside my Adapter
What's the cause of this error and where did I get this wrong?
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{
int i;
#NonNull
#Override
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_history_pending, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull RecyclerViewAdapter.ViewHolder holder, final int position) {
i = holder.getAdapterPosition();
holder.reference_number.setText("#"+mainActivity.myBookings.getCargoBooking().get(i).getReferenceNumber());
holder.btn_details.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String fee;
fee = isNull(mainActivity.myBookings.getCargoBooking().get(i).getCargoItem().get(0).getCargoFee().toString());
Intent i = new Intent(mainActivity.context, BookingDetailsActivity.class);
i.putExtra("fee", fee);
startActivity(i);
}
});
}
private String isNull(String s){
if (s != null){
return s;
} else return "";
}
#Override
public int getItemCount() {
return mainActivity.myBookings.getCargoBooking().size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView reference_number, driver_schedule;
Button btn_details;
public ViewHolder(View itemView) {
super(itemView);
reference_number = itemView.findViewById(R.id.tv_pending_trackNum);
driver_schedule = itemView.findViewById(R.id.tv_view_driver_schedule);
btn_details = itemView.findViewById(R.id.btn_pending_view);
}
}
}
Your problem is the "i" variable in your adapter scope, remove it and declare it as local (inside your onBindViewHolder method) and it should work.
That's because your instance variable i keeps changing whenever onBindViewHolder is called, say when the RecyclerView is being scrolled for example. Instead, change the variable i to local:
#Override
public void onBindViewHolder(#NonNull RecyclerViewAdapter.ViewHolder holder, final int position) {
final int i = holder.getAdapterPosition();
I really need some help regarding the recyclerview list.
Suppose there is a list with 10 items, Suppose i click one item (at position 1), i need make the view(button/image) visible on that particular item clicked. But when i will click any other item (at position 5) then the view(button/image)should be visible on position 5 and not on position 1. Can anyone tell me how can i achieve this result ? I would really appreciate if anybody help me with this. If you want some more details please do comment.
Thanks.
in recyclerview adapter when handling click listener in onBindViewHolder(Holder, Position) method you must choose the position of the view not fixed number(eg: 1,2 ,3)
ex:
=========
#Override
public void onBindViewHolder(final YourHolder holder, final int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
view.setVisibility(View.VISIBLE);
}
});
i hope this code is good enough to explain the way to do that:
public class myAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> list;
public myAdapter(List<Object> list){
this.list=list;
}
ItemViewHolder openedRow=null;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
ItemViewHolder view = new ItemViewHolder(v);
v.setOnClickListener(this);
return view;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
final ItemViewHolder myRowHolder = (ItemViewHolder) holder;
myRowHolder.itemView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
if(openedRow!=null)
{
openedRow.image.setVisibility(View.GONE);
}
openedRow=myRowHolder;
openedRow.image.setVisibility(View. VISIBLE);
}
});
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
ImageView image;
public ItemViewHolder(View itemView) {
super(itemView);
image = (ImageView)
itemView.findViewById(R.id.img_item_main);
}
}
}
I've updated mi code, this is working fine!
You need to add a boolean attribute to your ItemAdapter (the item you inflate on the recyclerView).
public class YourItem{
private String title;
private String image;
private boolean showView;
public String getTitle() {
return title;
}
public String getImage() {
return image;
}
public void setShowView(boolean showView) {
this.showView = showView;
}
public boolean mustShowView() {
return showView;
}
}
Then on your Adapter:
public class YourAdapter extends RecyclerView.Adapter<YourAdapter.MyViewHolder> {
...
private int lastPosition;
...
class MyViewHolder extends RecyclerView.ViewHolder {
private TextView title;
private ImageView image;
private View.OnClickListener onRowClicked = new View.OnClickListener() {
#Override
public void onClick(View view) {
if (lastPosition != getAdapterPosition()) {
Prize lastItem = getItem(lastPosition);
lastItem.setShowView(false);
adapterList.set(lastPosition, lastItem);
lastPosition = getAdapterPosition();
}
Prize item = getItem(getAdapterPosition());
item.setShowView(!item.mustShowView());
adapterList.set(getAdapterPosition(), item);
notifyDataSetChanged();
}
};
MyViewHolder(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
title = (TextView) itemView.findViewById(R.id.prize_title);
itemView.setOnClickListener(onRowClicked);
}
void bind(final Prize item) {
title.setText(item.getTitle().toUpperCase());
Picasso.with(context).load(item.getImage()).into(image);
image.setVisibility(item.mustShowView() ? View.VISIBLE : View.GONE);
}
}
}
I had this problem and change these:
1-Don't set attribute of android:visibility="visible" or "gone" in xml
2-Set this attribute in function of onBindViewHolder() in adapter():
holder.yourView.setVisibility(View.GONE);
holder.yourBottun.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!(holder.yourView.isShown() ) {
holder.yourView.setVisibility(View.VISIBLE);
}
}
});
I'm trying to set an onclick method in my RecyclerView. It worked on another project but not here. I searched on the web but can't figure it out. Not even the toast is popping up. Can someone, please, explain to me where I am making a mistake?
Here's my code:
private Context mContext;
private MenuImages[] mMenuImages;
public MenuAdapter(Context context, MenuImages[] menuImages){
mContext = context;
mMenuImages = menuImages;
}
#Override
public MenuViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.menu_list_item, parent, false);
MenuViewHolder viewHolder = new MenuViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(MenuViewHolder holder, int position) {
holder.bindMenu(mMenuImages[position]);
}
#Override
public int getItemCount() {
return mMenuImages.length;
}
public class MenuViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener{
public ImageView mImageView;
public TextView mTextView;
public MenuViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.itemImageView);
mTextView = (TextView) itemView.findViewById(R.id.textView2);
itemView.setOnClickListener(this);
}
public void bindMenu(MenuImages menuImage){
mImageView.setImageBitmap(menuImage.getImageMenu());
mTextView.setText(menuImage.getTitleImageMenu());
}
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), getLayoutPosition(), Toast.LENGTH_LONG).show();
}
}
in my case I was using RecyclerView in InterceptorCardView of other class wich was preventing onClickListener of recyclerview,
when I changed it with CardView and it worked perfectly
Note: I removed clickable = "false" ,focusable = "false".
it may be late but in your layout xml file you should add attribute clickable = "false" and also focusable = "false" to the children view ,textview and imageview in your case
I am using RecyclerView to show the list of items. I have two TextViews one below other. Initially the second TextView is set to singleline = true.Now on item click, I am setting singleline = false. This is just done to expand it on click (Like ExpandableList). The code works fine but the problem is that as RecyclerView uses the recycled item other items TextView values are also being set to singleline = false. Now how can I avoid this?
Code
public class InboxAdapter extends RecyclerView.Adapter<InboxAdapter.InboxViewHolder> {
private Context context;
private List<InboxModel> listInbox;
private InboxModel currentItem;
public InboxAdapter(Context context, List<InboxModel> listInbox) {
this.context = context;
this.listInbox = listInbox;
}
#Override
public InboxViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.custom_inbox_item, parent, false);
InboxViewHolder viewHolder = new InboxViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final InboxViewHolder holder, int position) {
currentItem = listInbox.get(position);
holder.tvHeader.setText(currentItem.header);
holder.tvMsg.setText(currentItem.msg);
holder.tvHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.tvMsg.setSingleLine(false);
LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams) holder.tvMsg.getLayoutParams();
lp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
holder.tvMsg.setLayoutParams(lp);
}
});
}
#Override
public int getItemCount() {
return listInbox.size();
}
class InboxViewHolder extends RecyclerView.ViewHolder {
private TextView tvImageHeader;
private TextView tvHeader;
private TextView tvMsg;
private TextView tvDate;
public InboxViewHolder(View itemView) {
super(itemView);
tvImageHeader = (TextView) itemView.findViewById(R.id.tv_img_header);
tvHeader = (TextView) itemView.findViewById(R.id.tv_header);
tvMsg = (TextView) itemView.findViewById(R.id.tv_msg);
tvDate = (TextView) itemView.findViewById(R.id.tv_date);
}
}
You have to set the attribute in all cases to avoid issues with the recycled items.
#Override
public void onBindViewHolder(final InboxViewHolder holder, int position){
//....
if (currentItem.myBoolean){
holder.tvMsg.setSingleLine(true);
} else {
holder.tvMsg.setSingleLine(false);
}
//...
}
In your click event just change the value inside the object (not the view!). Somenthing like:
holder.tvHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
currentItem.myBoolean = true;
//call the notify !
}
});
If this state is exclusive, instead of using a variable inside the item use a variable (InboxModel checkedItem) inside the Adapter.
Hmmm For that you have to saved click postion and write condition in onBindViewHolder() like below
#Override
public void onBindViewHolder(final InboxViewHolder holder, int position) {
if(Postion==Mysavedposition){
holder.tvMsg.setSingleLine(false);
}else{
holder.tvMsg.setSingleLine(true);
}
currentItem = listInbox.get(position);
holder.tvHeader.setText(currentItem.header);
holder.tvMsg.setText(currentItem.msg);
holder.tvHeader.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Mysavedposition=position;
holder.tvMsg.setSingleLine(false);
LinearLayout.LayoutParams lp= (LinearLayout.LayoutParams) holder.tvMsg.getLayoutParams();
lp=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
holder.tvMsg.setLayoutParams(lp);
}
});
}