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);
Related
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.
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.
I'm stuck on a little problem.
When I click on a row in my RecyclerView, I'd like to change its color to some other color (i.e.: red).
Then, if I click this row again, I would like to set its color back to the normal one (i.e.: white).
Then, if I click on a second row or n-th row, I would like to do the same.
I've tried to work on the RecyclerView Adapter class, in my ViewHolder I tried some ideas counting user clicks, setting a boolean to check the colored rows, and getAdapterPosition to know what is the row's position... but actually all my tries failed!
Would you please help me with that problem?
It seems that I'm close to the solution, but need a little help
You're going to need to keep track of which items were selected on the list (otherwise any changes to the view will simply be recycled).
Keep a list of selected items within your adapter. In the adapter's onBindViewHolder you can check against the list and if the list contains the view/item, you can color the view accordingly.
Edit: Refer here for a working example
How to properly highlight selected item on RecyclerView?
Here is an example of what I am saying in title. Take the app "Feedly". If there is even ONE item i your list, it looks like this:
Now, if the list is empty, there is a nice way to handle this to avoid a big, blank, white space, like so:
How can one achieve this?
Off hand I am thinking maybe this way, see my pseudo-code:
if (adapter.size < 1) {
// change ListView Background;
}
Check out the ListView#setEmptyView method.
If your have an empty ListView, the height should be 0 and it may be no use to set the background for ListView.
I have several solutions here:
Set the background for the LinearLayout/RelativeLayout, whatever which contain the ListView according to size of adapter.
Create another ImageView which is the "All read" image, and set its visibility according to data size of the ListView adapter.
Create a view for what you want to display when adapter size = 0, and use ViewSwitcher to switch between ListView and "All read" view according to adapter size. I will recommend this one since it may be more flexible for the "All read" view. You can have button, TextView, ImageView or whatever layout element you want to put in it.
2 and 3 are similar but using ViewSwitcher may make the code readability better than setting Visibility for views.
Here is an example for using ViewSwitcher.
All i need is an idea or path to continue searching, i have a list of items that i add to a listview adapter. And i am trying to make some items in the list to have a specific background color (as an example) when the activity loads. Something like having those rows "preselected". The method public ListView getListView() does not help me much.
Thank you either way.
Need to set Multiple Choice Mode via setChoiceMode(), and then you can call setItemChecked() for each of the items you want checked. Then you probably have to make a custom adapter that overrides getView(), cast the parent to ListView and ask if the View (a list item) you are getting at the position given is in fact checked by calling something like getCheckedItems() on the parent. Then you can do what ever you want with that view, like set its background color etc.