recyclerview.adapter resets radio-buttons - java

This is my problem:
https://youtu.be/k-N5uthYhYw
and this is my onBindViewHolder() method.
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.specName.setText(specList.get(position).getSpecName());
// Assign a tag number to later identify what radio-button
holder.specRadioBtn.setTag(new Integer(position));
/* Event listenr for longClick - we prob. won't use it, but it's here just in case */
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
Toast.makeText(context, "Long press", Toast.LENGTH_SHORT).show();
return false;
}
});
/* Little hack to select its Radio Button when a specific row is tapped */
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Turn rowSelectedFlag to true since the user selected this row
rowSelectedFlag = true;
// When the user taps on a row select that row's radio button
holder.specRadioBtn.setChecked(true);
// I'm not sure why, but locally the interface needs to be started by pointing it
// to where it should drive the data (to send the params)
tempInterface = new AdminUserSpecialty();
// Call the interface to send the data (row spec-name and id) back to AdminUserSpecialty
tempInterface.activateSpecSelect(specList.get(position).getSpecName().toString(),
specList.get(position).getSpecId().toString(), rowSelectedFlag);
int clickedPos = ((Integer) holder.specRadioBtn.getTag());
// Check if the radio button is already selected
if (holder.specRadioBtn.isChecked()) {
if (lastCheckedBtn != null) {
// Don't deselect if user taps on the same row several times
if (lastCheckedBtn == holder.specRadioBtn) {
// do nothing
}
// Otherwise do deselect the previously selected radio button
else {
lastCheckedBtn.setChecked(false);
}
}
lastCheckedBtn = holder.specRadioBtn;
lastCheckedPos = clickedPos;
}
// If radio is not checked set the lastCheckedBtn to null (reset counter)
else {
lastCheckedBtn = null;
}
}
});
/* ----------------------------------------------------------------------*/
}
I can't seem to preserve my radio-button selection on RecyclerView scroll. On scroll the selection becomes erratic and random. I understand that one of RecyclerView's features is to recycle rows as they leave the screen, but what do I need to do to keep my selection? Thanks much.

I know that this was answered already but if some of you are still looking for an easier answer and your application does not rely on the RecyclerView view recycling feature much (for example if you have a fixed size list of items...) you can always set your recycler view cache view size. That way it would not recycler your views hence it would not recycler the views and you will avoid copy selected values to another views...
yourRecyclerView..setItemViewCacheSize(yourItemList.size());

Save the checked / unchecked status of the radio button (you should use checkbox instead if you want to allow the user to select multiple items) to your model (i.e. your items in the list should have a field for this) when the onClick event happens. When you bind the ViewHolder, make sure you set checkbox's value to whatever you saved in your model.

It's happen because of the Recycling mechanism
(PS: its the same for the ListView or RecyclerView).
To fix that:
1) Add a booelan variable to your model to save the state of the RadioButton
2) Update your RadioButton state in onBindViewHolder() method from this boolean in the model.
3) Add setOnCheckedChangeListener() to your RadioButton to listen to his state (checked/unchecked) and to update the boolean in your model when the state changes.

Related

Radio button are not working normally in my Recycler View. Multiple Radio Buttons got selected of the view which are not visible with the focused one

I'm using a Recycler View to show all the images from the galley or the external storage of a device in a Grid Layout Manager. And I'm using a Radio Button to show if the image is selected or not.
PROBLEM
Whenever I select or deselect a Radio Button from the visible Views in the Recycler View some other Views which are outside the Visible Screen got selected or deselected.
It is like I'm pressing on the same View of the Recycler View, but the images are different.
PROBLEM
well that's because of the recycler view concept of reusing the views instead of creating new views every time you scroll.
you see if you have 100 items you want to show in a recycler view and only 20 of them could appear to the user, recycler view creates only 20 view holder to represent the 20 items, whenever the user scroll recycler view will still have 20 view holder only but will just switch the data stored in this view holders rather than create new view holders.
now to handle selection of your items there's two ways to do this.
the naive way
hold selection in a boolean array inside the recycle view adapter.
whenever the user scrolls, the adapter calls onBindViewHolder to update the visible viewholder with the proper data.
so when onBindViewHolder gets called just set the radio button selection according the boolean array using the position sent in the method call
at the end of your usage to the recycler view you can create a getter method in the adapter to get the selection array list of boolean and pass the data based on it
public class PhotosGalleryAdapter extends RecyclerView.Adapter<PhotosGalleryViewHolder> {
ArrayList<Your_Data_ClassType> data;
ArrayList<Boolean> dataSelected ;
public PhotosGalleryAdapter(ArrayList<Your_Data_ClassType> data) {
this.data = data;
dataSelected = new ArrayList<>(data.size()) ;
}
...
#Override
public void onBindViewHolder(#NonNull PhotosGalleryViewHolder holder, int position) {
...
RadioButton radioButton = holder.getRadioButton()
radioButton.setChecked(dataSelected.get(position));
radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
dataSelected.set(holder.getAbsoluteAdapterPosition() , isChecked) ;
}
});
...
}
}
the other way is to use a selection tracker and it should be the correct way to handle selections in a recycler view.
the problem with this way is it needs a lot of editing to the code and creating new classes to include as parameters in the selection tracker, but in the end you'll find it worth the time you spent on it.
in order to start with this way you need to do the following :
firstly, decide what should be a key (String-Long-Parcelable) so the tracker should use to differentiate between your data , the safest way is either String or Parcelable as I once tried Long and ended up with lots and lots of problems (in your case I will assume it's the photo's uri which will be of type string)
secondly, you need to create two new classes, one that extends ItemDetailsLookup, and the other extends ItemKeyProvider, and should use the key as their generic type (the type that is put between <> )
your two classes should look like this (that you might copy them straight forward)
the one that extends ItemKeyProvider :
public class GalleryItemKeyProvider extends ItemKeyProvider<String>{
PhotosGalleryAdapter adapter ;
/**
* Creates a new provider with the given scope.
*
* #param scope Scope can't be changed at runtime.
*/
public GalleryItemKeyProvider(int scope,PhotosGalleryAdapter m_adapter) {
super(scope);
this.adapter = m_adapter;
}
#Nullable
#Override
public String getKey(int position) {
return adapter.getKey(position);
}
#Override
public int getPosition(#NonNull String key) {
return adapter.getPosition(key);
}
}
the one that extends ItemDetailsLookup :
public class GalleryDetailsLookup extends ItemDetailsLookup<String> {
private final RecyclerView recView ;
public GalleryDetailsLookup(RecyclerView m_recView){
this.recView = m_recView;
}
#Nullable
#Override
public ItemDetails<String> getItemDetails(#NonNull MotionEvent e) {
View view = recView.findChildViewUnder(e.getX(), e.getY());
if (view != null) {
RecyclerView.ViewHolder holder = recView.getChildViewHolder(view);
if (holder instanceof PhotosGalleryViewHolder) {
return ((PhotosGalleryViewHolder) holder).getItemDetails();
}
}
return null;
}
}
thirdly, you should include this new two methods in your adapter to be used by the above classes
public class PhotosGalleryAdapter extends RecyclerView.Adapter<PhotosGalleryViewHolder> {
...
public String getKey(int position) {
return data.get(position).getUri();
}
public int getPosition(String key) {
for (int i = 0; i < data.size(); i++) {
if (data.get(i).getUri() == key) return i;
}
return 0;
}
...
}
forthly (if there's an english word called forthly), you should initialize the tracker with all the above classes that were created before and he will handle the rest, the tracker takes as parameters
a unique selection tracker id (if that will be the only selection tracker you will use then name it anything)
the ItemKeyProvider that we created
the DetailsLookup that we created
a String-Long-Parcelable Storage to store the keys that were selected in (in our case it will be a String Storage)
a Selection predicate, it's responsible to handle the way of selection you want to do, you want it to be able to (select only one item-multiple selection with no limits- based on a weird algorithm like even only or odd only), in my case I will use a default multiple selection one but if you want to alter it with another selection algorithm you should create a new class that extends SelectionPredicates and implement your way of selection, you could also just check the other default ones might be what you're looking for.
anyway, that's how the initialization should look (you should put this code wherever you initialize your recycler view at whether it's in fragment or activity method):
private void initRecycleView() {
...
SelectionTracker<String> tracker = new SelectionTracker.Builder<>("PhotosGallerySelection",
Your_Recycler_View,
new GalleryItemKeyProvider(ItemKeyProvider.SCOPE_MAPPED, photosAdapter),
new GalleryDetailsLookup(Your_Recycler_View),
StorageStrategy.createStringStorage())
.withSelectionPredicate(SelectionPredicates.createSelectAnything())
.build();
...
}
I didn't find a way to let me initialize the adapter with data and then create the tracker inorder to make the viewholders know about their selection or not, so in this case I firstly created the tracker and then made the adapter know about it's data using a setter and notifyDataSetChanged
what I mean by that is after creating the tracker instantly set the tracker and data to the adapter, so the initRecycleView should look like this
private void initRecycleView() {
...
SelectionTracker<String> tracker = new SelectionTracker.Builder<>("PhotosGallerySelection",
Your_Recycler_View,
new GalleryItemKeyProvider(ItemKeyProvider.SCOPE_MAPPED, photosAdapter),
new GalleryDetailsLookup(Your_Recycler_View),
StorageStrategy.createStringStorage())
.withSelectionPredicate(SelectionPredicates.createSelectAnything())
.build();
photosAdapter.setTracker(tracker);
photosAdapter.setData(data);
photosAdapter.notifyDataSetChanged();
...
}
Last but no least, you should handle how the view holders should know if they were selected or not, so you should let the adapter know about the tracker and its data by creating a setter method in it, that's how the adapter should look like in the end :
public class PhotosGalleryAdapter extends RecyclerView.Adapter<PhotosGalleryViewHolder> {
ArrayList<Your_Data_Class> data;
private SelectionTracker<String> tracker;
public PhotosGalleryAdapter() {
data = new ArrayList<>();
}
public ArrayList<Your_Data_Class> getData() {
return data;
}
public void setData(ArrayList<Your_Data_Class> m_data) {
this.data = m_data;
}
#Override
public ScheduleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
...
}
#Override
public void onBindViewHolder(#NonNull PhotosGalleryViewHolder holder, int position) {
...
boolean isSelected = tracker.isSelected(data.get(i).getUri());
RadioButton radioButton = holder.getRadioButton;
radioButton.setChecked(isSelected);
}
#Override
public int getItemCount() {
return data.size();
}
public String getKey(int position) {
return data.get(position).getUri();
}
public int getPosition(String key) {
for (int i = 0; i < data.size(); i++) {
if (data.get(i).getUri() == key) return i;
}
return 0;
}
public void setTracker(SelectionTracker<String> m_tracker) {
this.tracker = m_tracker;
}
}
(as you may notice if you initialized the adapter with its data through the constructor, when he asks the tracker if there were an item selected or not, it will result in a NullPointerException as at the moment of initializing the adapter you still didn't initialize the tracker)
that way you could keep track of your selection the way google suggests in their documentation (which I honestly don't know why the made it very complicate like that).
if you want to know all the selected item in the end of your application/fragment use, you should call tracker.getSelection() which will return a Selection List for you to iterate on
There's a tiny problem/feature with the tracker that it won't start selecting the first item until you use a long press on it, that happens only in the first item you select, if you do want this feature (start selecting mode by long press) then leave it as it is
incase you don't want it you can make the tracker select a ghost key (any unique string key that means nothing to your data) at the beginning which should later enable the selection mode with a simple click on any photo
tracker.select("");
this also the way to make a default/old selection at the beginning, you could make a for loop and call tracker.select(Key) if you do want the tracker to start with few items being selected
N.B : incase you use the Ghost Key method you should watchout that the selection array that will get returned when you call tracker.getSelection() will also contain this Ghost Key.
at the end if you do have the curiosity of reading about selection tracker in the documentation follow this link
or maybe if you know how to read kotlin follow this two links
implementing-selection-in-recyclerview
a guide to recyclerview selection
I was stuck in the selection problem for days before I figure how to do all that so I hope you find your way through it.
Omar Shawky has covered the solutions.
With my answer I will stress on the reason why someone may face this sort of an issues with recycler views and how to avoid this common issue in the future (avoiding pitfalls).
Reason:
This issue happens because RecyclerView recycles views. So a RecyclerView item's view once inflated can get reused to show another off screen (to be scrolled to) item. This helps reduces re-inflation of views which otherwise can be taxing.
So if the radio button of an item's view is selected, and the same view gets reused to show some other item, then that new item can also have a selected radio button.
Solution:
The simplest solution for such issues is to have an if else logic in your ViewHolder to provide logic for both selected and de-selected cases. We also do not rely on information from radio button itself for initial setup (we do not use radioButton.isSelected() at the time of setup)
e.g code to write inside your ViewHolder class:
private boolean isRadioButtonChecked = false; // ViewHolder class level variable. Default value is unchecked
// Now while binding in your ViewHolder class:
// Setup Radio button (assuming there is just one radio button for a recyclerView item).
// Handle both selected and de-selected cases like below (code can be simplified but elaborating for understanding):
if (isRadioButtonChecked) {
radioButton.setChecked(true);
} else {
radioButton.setChecked(false);
}
radioButton.setOnCheckedChangeListener(
(radioButton, isChecked) -> isRadioButtonChecked = isChecked);
Do not do any of the following while setting up:
private boolean isRadioButtonChecked = false; // class variable
//while binding do not only handle select case. We should handle both cases.
if (isRadioButtonChecked) { // --> Pitfall
radioButton.setChecked(true);
}
radioButton.setOnCheckedChangeListener((radioButton, isChecked) -> isRadioButtonChecked = isChecked);
OR
// During initial setup do not use radio button itself to get information.
if (radioButton.isChecked()) { // --> Pitfall
radioButton.setChecked();
}

RecyclerView items not repeating, but retaining changes of previous item that was in its slot

I am trying to implement a list of files that can be selected from the RecyclerView Adapter class. While I understand it is not a good idea, I feel if I am able to accomplish this from within said class, it would be really helpful in the future.
My list item (Each individual item view for the RecyclerView) has the following structure:
|--------|----------------|
| ICON | DATA |
|--------|----------------|
Problem:
When a file is selected (by touching the icon portion of a file item), I change the background of that item to another color to denote that it has been selected.
However, when I scroll down to about 25 items later, another file has the same background color even though it's not selected (it does not show up in Log.d as being selected, nor was it in the test ArrayList that was used to store selected files).
It seems as though the item is only retaining the background change of the previous occupant.
Solution attempts:
Previously, only the variables related to each list item were declared in the RecyclerView ViewHolder class and all changes were made in the onBindViewHolder method. Now, all changes to be made have been moved to the ViewHolder class inside a method called bind. There was no change in behavior.
If I set the default background image during the very first step in onBindViewHolder, the behavior changes such that the items do not retain changes of previous occupants. However, on scrolling back, the background change for the target item reverts to the default background image.
Code:
public class RVA extends RecyclerView.Adapter<RVA.RVH>
{
private LayoutInflater inf;
private ArrayList<File> items;
// The var below is used to track the no. of selected items
// globally within the RVA class.
private int numberOfSelectedItems = 0;
public RVA(ArrayList<File> _items)
{
items = _items;
}
#Override
public RVA.RVH onCreateViewHolder(ViewGroup parent, int viewType)
{
inf = LayoutInflater.from(parent.getContext());
return new RVH(inf, parent);
}
#Override
public void onBindViewHolder(RVA.RVH holder, int position)
{
File listItem = items.get(position);
// 'binding' each file element to a respective host container.
holder.bind(listItem);
}
#Override
public int getItemCount()
{
return items.size();
}
#Override
public long getItemId(int position)
{
return position;
}
// The ViewHolder class.
// Initially it was just declared as class.
// There was no change observed after the 'final' modifier was added.
final class RVH extends RecyclerView.ViewHolder
{
private Context context;
private LinearLayout itemSelector;
private ImageView itemIcon;
private TextView itemName;
private TextView itemSize;
public RVH(LayoutInflater inf, ViewGroup parent)
{
super(inf.inflate(R.layout.list_item, parent, false));
context = parent.getContext();
// This is the SECOND outermost LinearLayout of each file item View.
// It was previously the parent Layout, but there was no difference due to change.
itemSelector = itemView.findViewById(R.id.item_selector);
// This is the icon ImageView.
itemIcon = itemView.findViewById(R.id.item_icon);
// These are the data TextViews.
itemName = itemView.findViewById(R.id.item_id);
itemSize = itemView.findViewById(R.id.item_size);
}
// The 'bind' method that registers changes.
public void bind(File fileItem)
{
String listItemName = fileItem.getName();
itemName.setText(listItemName);
//---- These are just changes to the icons depending on type. Works fine.
if(fileItem.isDirectory())
{
itemIcon.setImageResource(R.drawable.directory_icon);
itemSize.setText("Directory");
}
else
{
itemSize.setText(fileItem.length() + " B");
if(listItemName.endsWith(".jpg") || listItemName.endsWith(".jpeg") || listItemName.endsWith(".png") || listItemName.endsWith(".gif"))
{
Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
}
else
{
itemIcon.setImageResource(R.drawable.file_icon);
}
}
//---- END
//---- This is the code which handles opening files according to type. Works fine.
itemSelector.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(numberOfSelectedItems == 0)
{
if(!itemSize.getText().toString().endsWith(" B"))
{
Intent loadListItemIntent = new Intent(context, DirectoryViewActivity.class);
loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
context.startActivity(loadListItemIntent);
}
else
{
if(itemName.getText().toString().endsWith(".jpg") || itemName.getText().toString().endsWith(".jpeg") || itemName.getText().toString().endsWith(".png") || itemName.getText().toString().endsWith(".gif"))
{
Glide.with(context).load(fileItem).centerCrop().into(itemIcon);
Intent loadListItemIntent = new Intent(context, ImageActivity.class);
loadListItemIntent.putExtra("ITEMPATH", fileItem.getPath());
context.startActivity(loadListItemIntent);
}
else
{
Toast.makeText(context, "File needs proper application.", Toast.LENGTH_SHORT).show();
}
}
}
}
});
//---- END
//---- !!! THIS SECTION is where the problem manifests.
itemIcon.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if(itemIcon.getTag().toString().equals("not_selected"))
{
// Incrementing based on selection.
++numberOfSelectedItems;
// Using a tag to identify/ denote whether item is selected.
itemIcon.setTag("selected");
// Changing the background & disabling file opening while in selection mode.
itemSelector.setBackgroundResource(R.drawable.list_item_selected);
itemSelector.setClickable(false);
itemSelector.setLongClickable(false);
// I use this odd method to send a message to the host Activity
// that we have entered selection mode & that the Activity should
// display some option buttons on the Action Bar.
if(context instanceof DirectoryViewActivity)
{
((DirectoryViewActivity)context).addSelectedItem(fileItem);
if(numberOfSelectedItems == 1)
{
((DirectoryViewActivity)context).setSelectionMode();
}
}
}
else
{
// Decrementing based on deselection.
--numberOfSelectedItems;
// Overwiting the tag to identify/ denote item is now unselected.
itemIcon.setTag("not_selected");
// Background changed back to default & file opening re-enabled.
itemSelector.setClickable(true);
itemSelector.setLongClickable(true);
itemSelector.setBackgroundResource(R.drawable.list_item_background);
// I use this method to send a message to the host Activity
// that we have exited selection mode & that the Activity should
// remove related option buttons from the Action Bar.
if(context instanceof DirectoryViewActivity)
{
((DirectoryViewActivity)context).removeSelectedItem(fileItem);
if(numberOfSelectedItems == 0)
{
((DirectoryViewActivity)context).voidSelectionMode();
}
}
}
}
});
}
}
}
This is because RecyclerView does not create views for all of your items in the list it create enough ViewHolder to fill up the screen and few more and when you scroll the old ViewHolder are bind to some other data in the adapter that is when the onBindViewHolder() is called , so basically what is happening here is you are setting the background of current ViewHolder on the screen and when you scroll the same ViewHolder in bind to the new data.
I think you have to check in the onBindViewHolder whether or not this is the item to which you want to set the background and then take the decision remove it if the item is not selected in the dataset set background if it is selected.

Adding an onClick to a part of a RecyclerView item

I've been working on an online shop type of application, and I've hit a bump: I've been tasked to add a favorites system, but I can't figure out how to enable pressing a button that's part of the RecyclerView item to add it to favorites.
(In this case, the heart, which is supposed to turn to a full heart when clicked)
Add a boolean value for favourite in your list . Initially , keep it false .
You need to have two drawables , one for selected state and another for unselected state .
In your onBindViewHolder , set the drawable on runtime on the basis of above condition .
if(list.isfav)
{
holder.ivHeart.setImageDrawable(ContextCompat.getDrawable(context,(R.drawable.selected));
}else{
holder.ivHeart.setImageDrawable(ContextCompat.getDrawable(context,(R.drawable.unselected));
}
Put onClick on this ivHeart eg:
holder.ivHeart.setOnClickListener(v -> {
if(list.isfav) {
list[adapterPosition].isfav = false;
}else{
list[adapterPosition].isfav = true;
}
notifyItemChanged(adapterPosition);
});
Dont forget to notify the item while changing item .
In your RecyclerView adapter's onBindViewHolder() method, add click listener to your view and change the drawable programmatically.
The code will be something like this
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
holder.your_like_imageview.setOnClickListener{
holder.your_like_imageview.setImageDrawable(ContextCompat.getDrawable(context,R.drawable.something_else));
};
}
I'm assuming you're using an ImageView for the heart. What you can do is set a click listener on that ImageView and process that click.
An ideal way to do this would be to use an interface to handle click events that you pass to the Adapter.
However you could do something like this in the onBindViewHolder method:
imageView.setOnClickListener {
// depending your logic change the tint for the icon or the drawable
onClick(data[position], addToWishlist)
notifyDataSetChanged()
}
The onClick method will receive the particular item and a flag to add or remove it from
the wishlist:
fun onClick(data: Data, addToWishlist: Boolean) {
// you can perform the addition/ deletion from the wishlist here
}

Is there a way to update listView item layout in android studio?

I'm making a button that when i click on him the visibility of a checkbox withing a listView will change. however it appears that the code run as expected but the visibailty is not udpateing. is there a way to update the item's visabilty?
mButtonEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for(int i = 0 ; i<calanders.size();i++){
View view = mListView.getAdapter().getView(i,null,mListView);
if(mButtonEdit.isSelected()){
print("button is selected");
CheckBox checkBox = view.findViewById(R.id.clockproperties_checkBox);
checkBox.setVisibility(View.GONE);
}else{
print("button is not selected");
CheckBox checkBox = view.findViewById(R.id.clockproperties_checkBox);
checkBox.setVisibility(View.VISIBLE);
}
}
mListView.getAdapter().
if(mButtonEdit.isSelected()){
mButtonEdit.setSelected(false);
}else{
mButtonEdit.setSelected(true);
}
}
});
You should never call the ListAdapter's getView() method. It is only supposed to be called by the system when scrolling though the ListView. Instead you need to update the list by calling mListView.getAdapter().notifyDataSetChanged().
Add a boolean field in the adapter and update its value when the button is clicked.
You can create a model/data class based on your data and keep a Boolean variable for checkbox visibility. So default make it false and on button click get the position of list-view item and update Boolean variable to true, and do adapter.notifyDataSetChanged().
You can also try with :
((YourAdapter) yourListView.getAdapter()).notifyDataSetChanged();

Multiple rows marked after every 10 rows instead of one in Recyclerview Viewholder

I am struggling to make sure that one item with its background is colored whenever I make an update to one of its attribute through API. What's remarkable is that after every 10 rows, the next one get its colored.
On RecyclerViewAdapter, I get all items according to the API in correct order but the problem is at the if statements: instead of objects where isfound or searching equals 1, it's multiple objects who also receives the background color. How can I fix it? Here is the necessary code:
RecyclerviewAdapter
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, final int position) {
Item item=this.items.get(position);
viewHolder.titleList.setText(item.getTitle());
viewHolder.descriptionList.setText(item.getDescription());
viewHolder.dateList.setText(item.getDate());
if (item.isFound()==1){
viewHolder.layoutList.setBackgroundColor(Color.parseColor("#60ad5e"));
}
if (item.isSearching()==1){
viewHolder.layoutList.setBackgroundColor(Color.parseColor("#ff9d3f"));
}
viewHolder.layoutList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Item item=items.get(position);
Intent intent = new Intent(context, DetailActivity.class);
intent.putExtra(EXTRA_MESSAGE, item);
context.startActivity(intent);
}
});
}
The recyclerview is inside the linearlayout in XML but its scrollable. Everything else works inside this code, clicking a certain item in list shos me more details of that item, etc. But its only the problem of multiple background coloring instead of one.
You should probably combine the if statements and add an else block. The views in a RecyclerView are re-used as you scroll, hence the name, so you need to reset them back to default when your flag(s) are not set.
if (item.isFound()==1){
viewHolder.layoutList.setBackgroundColor(Color.parseColor("#60ad5e"));
} else if (item.isSearching()==1){
viewHolder.layoutList.setBackgroundColor(Color.parseColor("#ff9d3f"));
} else {
// reset the color back to default
}

Categories

Resources