I'm trying just to make clicked items of ListView to change background. But it seems to me not actually possible. there are lots of posts with examples of doing that but none of them works reliably. As I understood - it's somehow related to "recycling".
I call view.setSelected() in adapter's OnItemClickListener and it nicely applies another background to selected item according to my settings. But when I select the item which causes ListView to lack space (not important how exactly) and a scollbar appears (or disappears) inside of ListView - android forgets my selection and the default style is applied. Same bug occurs when rotating screen - the item deselects. So I think that "deselection" occurs while adapter's getView() is being called.
It's interesting that my onClick event causes sending a json request to a background service and recieving and decoding a json response, so it takes some time between an item click and activity content change. This is how it looks:
Clicking on items which don't cause a scrollbar to appear works nicely - selected items do not become deselected after processing service's response.
Trying to call setSelected() inside of adapter's getView() gives no affect on the bug. Item still being deselected. I tried to set item's background manually in getView() - and it became more interesting: items which cause appearance of a scrollbar started to work properly, but items which don't cause apperance of scrollbar (actually it means that they don't cause getView() calling) stopped working!
All code is quite complex, so I'll post just some important fragments. Here's my OnItemClickListener:
private AdapterView.OnItemClickListener onCategoryClickListener =
new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, final View view, final int position,
long id) {
categoriesAdapter.setSelectedPosition(position);
view.setSelected(true);
// More code here
}
};
and here's a fragment of my Adapter's code:
private int selectedPosition;
private boolean selectable = true;
public void setSelectedPosition(int position) {
this.selectedPosition = position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = (TextView) View.inflate(context, textViewResourceId, null);
label.setText(getName(values.get(position)));
if(selectable) {
label.setBackgroundResource(R.drawable.list_selector);
if(position == selectedPosition) {
label.setSelected(true); // This does not work. Why?
label.setBackgroundColor( // This gives strange results
context.getResources().getColor(R.color.list_item_selected_color));
} else {
// Similar code here, but for deselecting items.
}
}
return label;
}
and here is my selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@color/list_item_default_color"
android:state_selected="false" />
<item
android:drawable="@color/list_item_selected_color"
android:state_selected="true"/>
</selector>
I searched a lot for how to make it work but nothing helps. Here are some things that I tried:
For API 11+:
1) Set list view to single choice:
<ListView
android:choiceMode="singleChoice" />
2) Set the background of the root element of your item layout to your selector:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@drawable/selector">
3) Change android:state_selected
to android:state_activated
:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/list_item_selected_color"
android:state_activated="true"/>
<item android:drawable="@color/list_item_default_color"/>
</selector>
4) Highlight item using listView.setItemChecked(index, true);
Note: To make it clear regarding view's states, specially state_activated
you can check this post; it is interesting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With