How to highlight row in ListView in Android?
It's much easier to implement this in your layout files and let Android handle the rest...
1) Make sure you have android:choiceMode=""
set on your ListView layout (singleChoice
, multipleChoice
, etc). By default it is set to none
.
<ListView
android:id="@+id/invite_friends_fragment_contacts_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="multipleChoice"/> <!-- THIS LINE -->
2) Create a state selector XML file and save it in your drawables folder. In this example, we'll name it state_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/blue" android:state_selected="true"/>
<item android:drawable="@android:color/blue" android:state_activated="true"/>
<item android:drawable="@android:color/transparent"/>
</selector>
3) In your list item layout, add the state_selector.xml file as the background:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/state_selector"> <!-- THIS LINE -->
<!-- ALL OF YOUR ELEMENTS WILL GO HERE (TextViews, ImageViews, etc) -->
</RelativeLayout>
If you are using multipleChoice
, you can override onItemClick()
and set/unset selected items accordingly. Android will change the background color as specified in your state_selector.xml file.
Just:
- Set the correct choice mode in your list view.
setChoiceMode
Set a background to support the selection state in you item layout, like:
android:background="?android:attr/activatedBackgroundIndicator"
FYI:
- http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
- http://android-developers.blogspot.mx/2008/12/touch-mode.html
Since by default ListViews
are set to a selection mode of NONE
, in touch mode the setSelection
method won't have visual effect.
For keeping the previous selection / visually display an explicit selection, first you must set your listview's choice mode appropriately:
listview.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
It's useful to read the API Docs of these methods:
- setSelection
void android.widget.AdapterView.setSelection(int position)
Sets the currently selected item. To support accessibility subclasses that override this method must invoke the overriden super method first.
Parameters:
position
Index (starting at 0) of the data item to be selected.
- setChoiceMode
void android.widget.ListView.setChoiceMode(int choiceMode)
Defines the choice behavior for the List. By default, Lists do not have any choice behavior (
CHOICE_MODE_NONE
). By setting the choiceMode toCHOICE_MODE_SINGLE
, the List allows up to one item to be in a chosen state. By setting the choiceMode toCHOICE_MODE_MULTIPLE
, the list allows any number of items to be chosen.Parameters:
choiceMode
One ofCHOICE_MODE_NONE
,CHOICE_MODE_SINGLE
, orCHOICE_MODE_MULTIPLE
In case this is not enough (say you'd like to always show the last selection differently beside the current selection), you should store your last selected item (a data which populates the ListAdapter
) as lastSelectedItem
, and in your adapter's getView
method assign a different background resource to the renderer if it equals this lastSelectedItem
.
If your last selection wouldn't refresh on selection change, you should explicitly call the notifyDataSetChanged
method on your adapter instance.
Update
Since your activity containing the ListView
is a child of an activity which waits for this one's result (based on the setResult(Activity.RESULT_OK,pongIntent);
part), the initial idea is correct, the last position should be passed through the intent when starting the activity:
selectedListItem = getIntent().getIntExtra("PositionInList", -1);
lvUsers.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
lvUsers.setSelection(selectedListItem);
The ListView.CHOICE_MODE_SINGLE
solution would work if you remain in the same activity, but you are finishing it on every itemClick (selection change), that's why the extra data should be passed to the starting Intent
.
You can also set the previously selected item's background from your adapter -as mentioned above-, overriding its getView
method:
lvUsers.setAdapter(new ArrayAdapter(this, R.id.counlistView, groups)
{
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
final View renderer = super.getView(position, convertView, parent);
if (position == selectedListItem)
{
//TODO: set the proper selection color here:
renderer.setBackgroundResource(android.R.color.darker_gray);
}
return renderer;
}
});