notifyDataSetChanged not working on when adapter change - android

I am getting data from server and then parsing it and storing it in a List. I am using this list for the RecyclerView's adapter. I am using Fragments.
I extended
RecyclerView.Adapter<RecyclerView.ViewHolder>
this my complete adapter class
public class GridAdapter extends RecyclerView.Adapter<GridAdapter.ViewHolder> {
private List<ProductModel> list;
ItemClickListener itemClickListener;
public GridAdapter(List<ProductModel> list, ItemClickListener itemClickListener) {
this.list = list;
this.itemClickListener = itemClickListener;
}
public void update(int position,ProductModel pm){
Log.v("update adapter",position+"");
list.set(position,pm);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.grid_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
final ProductModel cp = list.get(position);
holder.tvName.setText(cp.name);
holder.tvPrice.setText(cp.price);
holder.ratingBar.setRating(cp.rate);
Log.v("grid",cp.id + "=="+ cp.checked);
if(cp.checked==1){
holder.imgCheck.setVisibility(View.VISIBLE);
}else{
holder.imgCheck.setVisibility(View.GONE);
}
LayerDrawable stars = (LayerDrawable) holder.ratingBar.getProgressDrawable();
stars.getDrawable(2).setColorFilter(Color.YELLOW, PorterDuff.Mode.SRC_ATOP);
holder.lnrItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemClickListener.onItemClick(cp,position);
}
});
}
#Override
public int getItemCount() {
return list.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName, tvPrice;
ImageView imgMenu, imgCheck;
LinearLayout lnrItem;
RatingBar ratingBar;
public ViewHolder(View itemView) {
super(itemView);
lnrItem = itemView.findViewById(R.id.lnrItem);
imgMenu = itemView.findViewById(R.id.imgMenu);
imgCheck = itemView.findViewById(R.id.imgCheck);
tvName = itemView.findViewById(R.id.tvName);
ratingBar = itemView.findViewById(R.id.ratingBar);
tvPrice = itemView.findViewById(R.id.tvPrice);
}
}
}
and in fragment activity i use this code to load adapter to recyclerview
public void fillListProduct(List<ProductModel> mItems) { //method for load adapter for the first time
mAdapterGrid = new GridAdapter(mItems,this);
recGrid.setAdapter(mAdapterGrid);
}
void update(){ //method to change checked value
mAdapterGrid.update(cp.row,cp);
mAdapterGrid.notifyDataSetChanged();
}
in my custom adapter i have 3 variable lets call id, name, checked, everything work properly, in first load i set 0 as default value for checked, in my scenario user can change checked value by tap the row of recycleview.
my question is, when user tap desire row then checked will change from 0 to 1 and display it to recycelview, i already use notifydatasetchange() but not working.
Please help.
thanks

Try to remove mAdapterGrid.notifyDataSetChanged();
and modify this function in your adpater:
public void update(int position,ProductModel pm){
Log.v("update adapter",position+"");
list.set(position,pm);
notifyItemChanged(position);
}

Related

Dynamically Calculate Sum on RecyclerView Android

App Screen
I want to automatically get the sum of the items once added in the recycler view and at the same time get the sum of the items when the Quantity changes and when an item from the recyclerView is removed. I am new in Android, and I cannot think of any way to achieve this. I am thinking something like the code below, but I don't know how to implement it.
TextView ProductPrice = itemView.findViewById(R.id.productPricelbl);
TextView QTY = itemView.findViewById(R.id.Quantity);
Int total;
private void GetTotal(){
total += Integer.parseInt(ProductPrice.getText().toString()) * Integer.parseInt(QTY .getText().toString())
}
I am using a custom adapter for my recycler view with the code below
public class ListViewAdapter extends RecyclerView.Adapter<DemoVH>{
ArrayList<ProductListViewModel> productList;
Context mContext;
public ListViewAdapter(ArrayList<ProductListViewModel> productList, Context context) {
this.productList = productList;
this.mContext = context;
}
#NonNull
#Override
public DemoVH onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.recycler_view_row,parent,false);
return new DemoVH(view).linkadapter(this);
}
#Override
public void onBindViewHolder(#NonNull DemoVH holder, int position) {
final ProductListViewModel productListViewModel = productList.get(position);
holder.Product_Name.setText(productListViewModel.getProductName());
holder.Product_Barcode.setText(productListViewModel.getProductBarcode());
holder.Product_Price.setText(productListViewModel.getProductPrice());
}
#Override
public int getItemCount() {
return productList.size();
}
}
class DemoVH extends RecyclerView.ViewHolder{
TextView Product_Name;
TextView Product_Barcode;
TextView Product_Price;
TextView Product_QTY;
ImageView addQTY;
ImageView lessQTY;
private ListViewAdapter myAdapter;
int Quantity = 1;
public DemoVH(#NonNull View itemView) {
super(itemView);
Product_Name = itemView.findViewById(R.id.ProductNameLbl);
Product_Barcode = itemView.findViewById(R.id.ProductBarcodeLbl);
Product_Price = itemView.findViewById(R.id.ProductPriceLbl);
Product_QTY = itemView.findViewById(R.id.QTYLbl);
addQTY = itemView.findViewById(R.id.AddQTYBtn);
lessQTY = itemView.findViewById(R.id.lessQTYBtn);
itemView.findViewById(R.id.RemoveBtn).setOnClickListener(view -> {
myAdapter.productList.remove(getAdapterPosition());
myAdapter.notifyItemRemoved(getAdapterPosition());
});
addQTY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Quantity = Quantity+=1;
Product_QTY.setText(String.valueOf(Quantity));
}
});
lessQTY.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(Quantity == 1){
Product_QTY.setText("1");
}else{
Quantity = Quantity-=1;
Product_QTY.setText(String.valueOf(Quantity));
}
}
});
}
public DemoVH linkadapter(ListViewAdapter adapter){
myAdapter = adapter;
return this;
}
}
You can take a global variable in recycler view adapter and keep adding the amount in that variable in onBindViewHolder().
And when any item is increased or decreased or removed you can add or decrease that amount from that global variable.

hide/show a view(image or button) on a single item click in a recyclerview list

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);
}
}
});

Update the recycler view textview?

I have a RecyclerView defined in my android project. The Adapter for the RecyclerView is as follows
public class CustomAdapter1 extends RecyclerView.Adapter<CustomAdapter1.MyViewHolder> {
private Fragment1 myFrag;
private ArrayList<DataModel1> dataSet;
DBHandler db;
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView butAccept,butReject;
TextView nick,stat,tit,cat,desc,dt;
public CardView cardView;
public MyViewHolder(View itemView) {
super(itemView);
this.nick = (TextView) itemView.findViewById(R.id.nick);
this.stat = (TextView) itemView.findViewById(R.id.stat);
this.tit = (TextView) itemView.findViewById(R.id.tit);
this.cat = (TextView) itemView.findViewById(R.id.cat);
this.desc = (TextView) itemView.findViewById(R.id.desc);
this.dt = (TextView) itemView.findViewById(R.id.dt);
this.butAccept = (TextView)itemView.findViewById(R.id.accept_textview);
cardView = (CardView) itemView.findViewById(R.id.card_view);
cardView.setOnClickListener(this);
butAccept.setOnClickListener(this);
db = new DBHandler(itemView.getContext());
}
#Override
public void onClick(View v) {
if( v.getId() == butAccept.getId()){
String x = String.valueOf(dataSet.get(getAdapterPosition()).getMeetId());
myFrag.showToast(x);
}
}
}
public CustomAdapter1(ArrayList<DataModel1> data,Fragment1 frag) {
this.dataSet = data;
myFrag = frag;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent,int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardfrag1, parent, false);
MyViewHolder myViewHolder = new MyViewHolder(view);
return myViewHolder;
}
#Override
public void onBindViewHolder(final MyViewHolder holder,final int listPosition) {
TextView nick = holder.nick;
TextView stat = holder.stat;
TextView tit = holder.tit;
TextView cat = holder.cat;
TextView desc = holder.desc;
TextView dt= holder.dt;
nick.setText(dataSet.get(listPosition).getNick());
stat.setText(dataSet.get(listPosition).getStat());
tit.setText(dataSet.get(listPosition).getTit());
cat.setText(dataSet.get(listPosition).getCat());
desc.setText(dataSet.get(listPosition).getDesc());
dt.setText(dataSet.get(listPosition).getDt());
}
#Override
public int getItemCount() {
return dataSet.size();
}
}
The final TextView butAccept has dynamic values.I have an internal DB that has the column Status. When the value of the Status is 1 I need to change the text that is being displayed in the TextView butAccept.
How should I do this? Should I write a function in my CustomAdapter, or in the fragment in which I am using the adapter?
In my Fragment I have a function :
private void checkTheAcceptStatus(int x){
int status = db.getMeetingStatus(x);
Toast.makeText(getActivity(),String.valueOf(status),Toast.LENGTH_SHORT).show();
if(status == 1){
}
}
This function is being called everytime a new item is added to the adapter. The internal DB is being queried correctly and if the value of Status is being returned. If the value is 1 what should I do?
I saw this question, but this is unclear and I was unable to come to any conclusion from this.
If I understood correctly every row in your list has this accept button. So in your onBindViewHolder() you cant set the buttons text depending on the state of your status variable. When you detect changes in your db you can use the various notify methods provided depending on your needs: notifyItemChanged(...), notifyItemRangeChanged(...), notifyItemAdded(...), notifyItemRemoved(...) etc. Your onBindViewHolder should look something like this:
#Override
public void onBindViewHolder(final ViewHolder vh, int position) {
if(dataSet.get(position).getStatus() == 1){
vh.butAccept.setText("Your status 1 case text here");
} else {
vh.butAccept.setText("Your status not 1 case text here");
}
}
Also you can just use notifyDataSetChanged() if you want to refresh the whole list, but the methods above are more efficient.

One RecyclerAdapter for two activity

I make app with a couple of different categories of pictures. I want to display those pictures with RecyclerView.
I want to display button as a image when I clicked button before.
Can I make it in one adapter? Now I have two adapters, that code is as follow:
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private int[] images = {
R.drawable.imageA1, .... R.drawable.imageA10
};
private int[] images2 = {
R.drawable.imageB1, .... R.drawable.imageB10
};
class ViewHolder extends RecyclerView.ViewHolder{
public int currentItem;
public ImageView itemImage, itemImage2;
public TextView itemTitle;
public ViewHolder(View itemView) {
super(itemView);
itemImage = (ImageView)itemView.findViewById(R.id.imageView);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.article_layout, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.itemImage.setImageResource(images[i]);
}
#Override
public int getItemCount() {
return images.length;
}
}
You can set method in adapter that you will call when users clicks button:
// for button A
public void setImages() {
this.showImages = true;
}
// for button B
public void setImages2() {
this.showImages = false;
}
Then modify your on bind method to bind appropriate images:
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
if (this.showImages)
viewHolder.itemImage.setImageResource(images[i]);
else
viewHolder.itemImage.setImageResource(images2[i]);
}
You need to pass images array dynamically to your adapter as below
private int[] images = {
R.drawable.imageA1, .... R.drawable.imageA10
};
private int[] images2 = {
R.drawable.imageB1, .... R.drawable.imageB10
};
on click of button A
RecyclerAdapter myAdapter = new RecyclerAdapter(images)
yourRecyclerview.setAdapter(myAdapter )
on click of button B
RecyclerAdapter myAdapter = new RecyclerAdapter(images2)
yourRecyclerview.setAdapter(myAdapter )
change in your adapter as following
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private int[] images = new int[];
public RecyclerAdapter(int[] imgs){
images = imgs;
}
class ViewHolder extends RecyclerView.ViewHolder{
public int currentItem;
public ImageView itemImage, itemImage2;
public TextView itemTitle;
public ViewHolder(View itemView) {
super(itemView);
itemImage = (ImageView)itemView.findViewById(R.id.imageView);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.article_layout, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
viewHolder.itemImage.setImageResource(images[i]);
}
#Override
public int getItemCount() {
return images.length;
}
}
Yes possible. make constructor in adpater like that:
public RecyclerAdapter(Context context,int[] images)
{
this.diff_images=images;
this.context=context;
}
the diff_images is also int array in adapter class.
and make images array in your activity class. when you press button one then pass image1 array in adpater and if when press button2 then pass image2 array (if your want to show same view for both cases and if you want to show different view for both images)
if your adapter already set like:
recycleViewAdapter = new RecyclerAdapter(this, imageArray);
recyclerView.setAdapter(recycleViewAdapter);
then you can also make one more method in adapter class and only notify adapter for update image
public void setNewImageList(Context context, int[] imageArray) {
this.context = context;
this.diff_images = imageArray;
notifyDataSetChanged();
}
try this.

Selected image in recyclerview is get unselected upon scroll

In my recyclerview has one imageview and textview. I'm changing image of ImageView onn onClickListener. Now the problem is if i click on image of position 3 and scroll down... image of position 8 is also changed and again if i scroll up...image of position 2 is changed.
public class PortraitListviewAdapter extends RecyclerView.Adapter<PortraitListviewAdapter.ViewHolder> {
Context context;
static List<PortraitParentListAdapterBean> list;
static List<String> selectedPosition ;
public PortraitListviewAdapter(Context context, List<PortraitParentListAdapterBean> list) {
this.context = context;
this.list = list;
selectedPosition = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listview_parent_portrait, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
PortraitParentListAdapterBean portBean = list.get(position);
Log.i("pos",position+"");
holder.parentHeading.setText(portBean.getHeading());
if (selectedPosition.contains(list.get(position).getHeading())){
holder.parentImage.setImageResource(R.drawable.sad);
}
}
#Override
public int getItemCount() {
return list.size();
}
static class ViewHolder extends RecyclerView.ViewHolder {
protected TextView parentHeading;
protected ImageView parentImage;
public ViewHolder(View itemView) {
super(itemView);
parentHeading = (TextView)itemView.findViewById(R.id.parent_heading);
parentImage = (ImageView)itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedPosition.add(list.get(getAdapterPosition()).getHeading());
parentImage.setImageResource(R.drawable.sad);
}
});
}
}
}
the above code is my implementation for recyclerview adapter. please help to understand the concept.
SOLUTION
change
if (selectedPosition.contains(list.get(position).getHeading())){
holder.parentImage.setImageResource(R.drawable.sad);
}
with
if (selectedPosition.contains(list.get(position).getHeading())){
holder.parentImage.setImageResource(R.drawable.sad);
} else {
holder.parentImage.setImageResource(R.drawable.your_default_drawable);
}
EXPLANATION
When you scroll your RecyclerView the system doesn't recreate always your ViewHolder but reuse one you previously scrolled that is no longer visible, so you need to reset your standard values in order to avoid showing wrong values.

Categories

Resources