ListView item backgrounds not changing
I have an unusual issue with my ListView
. I currently have a "deselectAll()
" method which iterates through the items in my ListView and sets them to unchecked (the items implement the Checkable
interface). The "checked" variable gets changed correctly (the view reports as not being checked), but the visual indicator (in this case, a background change) does not show the view as unchecked (the background stays the color of a checked item).
I am iterating and deselecting through my listview like so (I also added my declerations):
private ListView vw_entryList;
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
((Entry)vw_entryList.getItemAtPosition(i)).setChecked(false);
}
}
The code for my implemented setChecked()
is 开发者_JS百科as follows:
public void setChecked(boolean checked) {
_checked = checked;
if (checked) {
setBackgroundResource(R.drawable.listview_checked);
}
else {
setBackgroundResource(R.drawable.listview_unchecked);
}
invalidate();
}
It should be noted that when the items are clicked, they are toggled between checked and unchecked in the OnItemClickListener
, and this works ok, with the background change and everything. The code for toggling is very similar:
public void toggle() {
_checked = !_checked;
setBackgroundResource(_checked ?
R.drawable.listview_checked : R.drawable.listview_unchecked);
invalidate();
}
The only difference I can see is where the methods are called from. toggle()
is called from within the OnItemClickListener.onClick()
method, while my deselectAll()
is called from within a button's standard OnClickListener
, both in the same class. Does anyone have any ideas as to why the background doesn't change when I call my deselectAll() function?
Do you have custom, non-standard color for the background? If so you might take a look at http://www.curious-creature.org/2008/12/22/why-is-my-list-black-an-android-optimization/ - it boils down to setting android:cacheColorHint attribute of your list to the background color. Maybe that will help.
Edited after further discussion:
I think you need to call getAdapter().notifyDataSetChanged() on the List rather than invalidate(). List is really build in the way that it is relying on adapter to provide the data. What you are doing in fact you have an implicit adapter - Entry is really kept in the adapter and by setting checked, you are changing the data model really, but if you do not call notifyDataSetChanged() the list does not really know that the model has changed and will not recreate the views (invalidate() will only redraw the existing ones).
After trying everything (thanks for your help Jarek), I found a solution that works for my purposes. Instead of implicitly calling the setChecked()
within the view that was clicked, I leave it up to the setItemChecked()
method within the ListView
class.
My updated code:
private void deselectAll() {
for (int i = 0; i < sAdapter.getCount(); i++) {
vw_entryList.setItemChecked(i, false);
}
}
My best guess is that the ListView
knows that its items implement the Checkable
class, and thus requires itself to be the handler of all item operations. Something along those lines. If anyone can explain in more detail why this solution works while the others did not, I'll reward them with the answer and an upvote.
精彩评论