How to change single item in RecyclerView without changing other layouts - android

I'm trying to toggle the background color of a single item in a RecyclerView on click. I do this in the onClick function of a ViewHolder that implements OnClickListener. Here is the onClick implementation:
int position = getLayoutPosition();
if (selected.containsKey(position)) {
view.setBackgroundColor(context.getResources().getColor(R.color.white));
selected.remove(position);
} else {
view.setBackgroundColor(context.getResources().getColor(R.color.highlight));
selected.put(position, view);
}
The issue arises when I test this in a populated RecyclerView. If there are many items, selecting one at the start also highlights other items further in the list that are out of view. The other highlighted views are not added to the map 'selected'. Also, after scrolling away from selected views and returning to them, they sometimes change colors. Why does this happen, and how can I fix this?

That is a side effect of the views being recycled. They are literally being reused. Just make sure when your views are being bound you explicitly set the background color to the default color. That should do it.

Related

Recyclerview Setting BackGround of Item

I have a simple horizontal recyclerview. As the user scrolls, the current item looses focus has background set to transparent and the new focused item is to have its background color changed to green. I have a simple method that takes in the focused position, changes it's color and sets the reset of the items to transparent.
public void resetRecycleColor(int rowindex){
for(int i=0; i < mRecyclerView.getAdapter().getItemCount(); i++){
if(i== this.rowindex){
Log.v("SCROLLS ", "COLOR GREEN "+ i);
mRecyclerView.getLayoutManager().findViewByPosition(i).setBackgroundColor(Color.GREEN);
}else{
Log.v("SCROLLS ", "COLOR TRANSPARENT "+i );
mRecyclerView.getLayoutManager().findViewByPosition(i).setBackgroundResource(R.color.gridBackgroundBlack);
}
}
}
Am I attempting to change the item background correctly? Something is wrong because it crashes on the line where the color is set. Comment out those lines and scrolling works fine. Can somebody point out why the crash may occur?
Thanks
You don't seem to understand the ViewHolder pattern.
You only have enough views (plus about 2) to fill RecyclerView. For example if you have 2000 items but they are represented in list that shows 3 items each, you only have 5 ViewHolders created. That way when scrolling views that exit the screen, reenter from the other side but displayed values are changed (in OnBindViewHolder).
Crash is occurring in findViewByPosition(i) since you're trying to get views for entire list but you only have views for a few of them, so this returns null.
I don't understand your use case entirely, but if you're repeatedly calling your method during onScroll then it has really bad performance, cleaner solution would be modifying your adapters onBindViewHolder to properly modify focused view and calling notifyItemChanged() to trigger rebinds on new/old focused view.

Setting border to a recylerview element reproduces on scrolling back to the same object

I have a recycler view of image views and upon longpress I try to give the image view a border. When I scrolldown and come back to the same object the boder is found on someother image.(It is ok coz... the recycler view deletes itself and creates back and so the position changes).
So what I did is I stored the image URl on long press and after scrolling back I drew the Border on the image based on the image URL.
Now the problem is the border that came previously(wrong position) is also drawn....how to get rid of it.
In simple terms. How to make the recyclerview forget the data changes?
(Notifydatasetchanged....Something like that)....
thankz in advance....
This is the problem caused by the position at which the boarder was made is not the same position after the scroll on RecyclerView you can easily fix this by allowing your object to remember if it was selected by long-press or not
Assume this is the class you have
class Item {
// here you already have your instance variables
// add another one
boolean isSelected;
}
when you long-press on an item make this instance variable of respective Item, true and provide it a boarder.
when you populate your List in RecyclerView's adapter what you can check is if the isSelected is true than make respective imageView have a boarder. otherwise don't
by doing so you will be independent of the position of the item with respective of the scroll. So your Item will retain the boarder which was actually selected.

ListView items change background color

I'm having a weird behaviour in my application... A have a ListView, where odd items have #ffffff background and even items have #f2f7f7, and looks like this:
However, as soon as I start scrolling the list, the even items slightly change color, becoming #f7f7f7, like this:
Any ideas? If you need more info, please ask. I'm baffeld with this behaviour.
Additional info:
I'm setting each item's background color in getView() method, like this:
protected final int[] colors = new int[] { R.drawable.states_list_odd, R.drawable.states_list_even };
...
// Alternates list items' background
int colorPos = position % colors.length;
convertView.setBackgroundResource(colors[colorPos]);
Simple stuff, actually. android:scrollingCache="false" solved this issue.
The Views used for the items are being reused when you scroll the list (there's no need to create the new ones). So, when you scroll down the list, the item at position 0 may be rendered at position 10. It will be the same View object, and before showing getView will be called with convertView parameter set to this particular View - so you can fill it with data (and specify your styles). It's just an optimization.
So, you need to specify the background color for the item each time getView is called for it in your list adapter.
programmaticly try this. yourListView.setScrollingCacheEnabled(false);

disabling and greying out list items

I have a list view. In that list view, I have to grey out and disable some items, and enable the rest list items with seperate color. How to do this?
You should write a custom adapter extending BaseAdapter for your ListView. To disable certain items, you have to override the "boolean isEnabled(int position)" in this adapter, and return false for every position you'd like to be disabled.
As for changing the background color for certain list elements: you could store the background color value in the data structure you're displaying. In your custom adapter's 'getView()' method, you should check this color value for the current element, and return a View with the correct background color set.
Or you could just call 'getChildAt()' on the ListView, getting back the View object for the desired element in the list, and change it's background color. I think I'd rather use the previous solution.
Remember to call 'notifyDataSetChanged()' on your ListView's adapter after you make changes like this.

Android list with 'grayed out' items

In Android, I want to present the user with a list. When an item on the list is selected some action is performed, and this list item is no longer selectable. It is also 'grayed out' or the like to indicate that it cannot be selected the next time the list is displayed. I have seen the isSelectable() override in Adapter, but I believe this causes the item to be treated as a separator, which causes visual problems. And I have not found a way to 'gray out' an item. Any ideas? Thanks...
As far as graying out an item. I'm not sure if this is the best way, but it's what I do:
view.setAlpha(75);
view.setBackgroundColor(Color.GRAY);
I'm basically making the item transparent and then setting the background color to gray. If you're reusing your list items you should also change them back to their original state if the condition is not met, i.e.:
view.setAlpha(255);
view.setBackgroundColor(Color.WHITE);
that is, if your original state was no transparency and the background color was white.
You need the view to be disabled. If you are creating the views just call .setDisabled(boolean) on the top view. Setting the list item to be disabled doesn't work very well in my experience.
Here is the solution I am using. I set up an OnItemClickListener for my ListView. When an item in the list is clicked, I take the passed in View and call setEnabled(false) on it. This will gray out the item. However, subsequent clicks on this item will still call the onItemClick method. So, you will need to check on each click if the item is enabled/disabled and act accordingly.

Categories

Resources