37

I have a list of albums (several hundred). When I touch the selected album I want to offer the user a choice of playing the whole album, or moving to its track ListView. No problem. However, after touching the ablum in albumListView I want the row to remain highlighted so the user knows which item they have clicked on, and can then move to OK or PLAY. How do I highlight a row in ListView?

12 Answers12

42

Other solution (mostly in XML)

1) set the choiceMode of the ListView to singleChoice

<ListView
    android:choiceMode="singleChoice"
.../>

2) Items of the list must be a Checkable View and use a Color State List as Background

eg: album_item.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:background="@drawable/list_selector"
.../>

3) the background Color State (list_selector.xml) defines the highlight color

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/green" android:state_checked="true"/>
    <item android:drawable="@color/green" android:state_pressed="true"/>
</selector>
Hiep
  • 2,483
  • 1
  • 25
  • 32
  • 3
    Tried this and it is a nice solution! – Boy Apr 21 '13 at 18:41
  • 5
    the most important thing here is step 1, others they are not necessary. And for the background style, simply define in the item: android:background="?android:attr/activatedBackgroundIndicator" – unruledboy Aug 23 '13 at 03:05
  • unruledboy> How do you control what the selected row color is? – Jasper Jul 10 '15 at 17:58
  • 2
    How do you make the selection color stay? It just shows color momentarily and then vanishes – Jasper Jul 10 '15 at 18:21
35

Quoted from http://android-developers.blogspot.de/2008/12/touch-mode.html

Imagine a simple application, ApiDemos for example, that shows a list of text items. The user can freely navigate through the list using the trackball but also, alternatively, scroll and fling the list using the touch screen. The issue in this scenario is how to handle the selection properly when the user manipulates the list through the touch screen.

In this case, if the user selects an item at the top of the list and then flings the list towards the bottom, what should happen to the selection? Should it remain on the item and scroll off the screen? What should happen if the user then decided to move the selection with the trackball? Or worse, what should happen if the user presses the trackball to act upon the currently selected item, which is not shown on screen anymore?

After careful consideration, we decided to remove the selection altogether, when the user manipulates the UI through the touch screen.

In touch mode, there is no focus and no selection. Any selected item in a list of in a grid becomes unselected as soon as the user enters touch mode. Similarly, any focused widgets become unfocused when the user enters touch mode. The image below illustrates what happens when the user touches a list after selecting an item with the trackball.

Community
  • 1
  • 1
Maaalte
  • 6,011
  • 3
  • 29
  • 27
  • In that case, can I use onClick to add a highlight? –  Feb 20 '11 at 17:20
  • An onClickListener would be one solution, or you can try adamp's approach – Maaalte Feb 20 '11 at 17:30
  • 21
    And yet, in the settings, in gmail, ..., they implemented lists where the selected item remains highlighted (which is much more convenient of course). Their argument certainly hasn't been carefully considered as they claim, nothing wrong is keeping an item highlighted even if the user scrolls it out of the screen. – RedGlyph Apr 30 '13 at 20:26
19

Maaalte is correct, in touch mode lists do not show the focus highlight on a current item since there is no current item in touch mode. Stateful selection like you're describing that persists while you interact with other parts of the UI is another matter though.

You can use CHOICE_MODE_SINGLE to express a stateful selection in a list. It will treat selection as a checked state. As long as the view that your adapter returns implements the Checkable interface, you can display the selected state however you choose. (Setting a background on the item view or otherwise. It does not actually need to show a check box widget.) You can then use the item checked methods of ListView to manipulate or determine the selection.

adamp
  • 28,862
  • 9
  • 81
  • 69
12

I solved this by extending the ListView and overriding the getView() method. I kept an internal identifier for the "selected" state and changed the background of the item according to it, like this:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View currView = super.getView(position, convertView, parent);
StateListItem currItem = getItem(position);
if (currItem.isItemSelected) {
    currView.setBackgroundColor(Color.RED);
} else {
    currView.setBackgroundColor(Color.BLACK);
}
return currView;
}  

I have an example program on my blog post: http://udinic.wordpress.com/2011/07/01/selectablelistview-make-selection-work/

Udinic
  • 3,014
  • 2
  • 25
  • 32
11

Here is my solution Listview:

<ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/white"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="1dp"
        android:paddingLeft="10dip"
        android:paddingRight="10dip"
        android:choiceMode="singleChoice"
        android:paddingTop="8dip" >
    </ListView>

Write a selector for list_row as

<!-- <item android:drawable="@color/android:transparent"  android:state_selected="true" /> -->
<item android:drawable="@android:color/darker_gray" android:state_selected="true"/>
<item android:drawable="@android:color/darker_gray" android:state_activated="true"/>    
<item android:drawable="@android:color/darker_gray" android:state_pressed="true"/>
<item android:drawable="@color/android:transparent"/>

Make sure you have item for state_activated=true

Then add this selector as your list_row background

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@drawable/listitem_selector"
  android:orientation="vertical" >

<TextView
    android:id="@+id/itemName"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

subair_a
  • 1,028
  • 2
  • 14
  • 19
6

add android:background="?activatedBackgroundIndicator
to list item's main layout similar to android.R.layout.simple_list_item_activated_2.xml

alicanbatur
  • 2,172
  • 1
  • 28
  • 36
denis
  • 73
  • 1
  • 3
5

Implement your list with single choice mode: android:choiceMode=singleChoice

Just as the default android.R.layout.simple_list_item_single_choice uses a RadioButton to denote the selected choice, you can implement a custom highlight state or similar in your list item layout to respond to the choice changes. Methods like getCheckedItemPosition() can be used by your application to determine which item the user currently has chosen, if necessary.

Hope that Helps!

devunwired
  • 62,780
  • 12
  • 127
  • 139
4

I know that it's two years since this question was last active, but just in case someone else needs it in the future. Here's my ListView xml code

<ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/results"
        android:choiceMode="singleChoice"
        android:listSelector="#ffdb700b"/>

You want to change the android:listSelector value.

jrsall92
  • 572
  • 1
  • 5
  • 19
3

Following solution can be used for highlighting one ore many list items. Starting point: There is a ListFragment to show a List of MyEntity via an ArrayAdapter implementation. The color of an TextView as part of the item layout has to change to grey, if the item is selected. Multiple items should be selectable.

  1. The ListFragment must provide an OnItemSelectListener(YourEntity item) that will be called in onListItemClicked().

    public void onListItemClick(ListView l, View v, int position, long id) {
      MyEntity entity = (MyEntity) getListView().getItemAtPosition(position);
      if (entityListSelectListener != null) 
        itemSelectListener.onItemSelect(entity); }
    
  2. The ArrayAdapter owns a List for the key fields for the selected items and provides the manager methods addSelection(MyEntity) and clearAllSelections(). The overriden method getView() reads the key field list and, if the actual position is in there, changes the particular TextView color to grey, otherwise to transparent.

    public View getView(int position, View convertView, ViewGroup parent) {
      ...
      if (selectedEntityList.contains(entity.key)) //... highlight view field }
    
  3. In onCreate() of the owning activity the listeners has to be implemented to manage the ArrayAdapter: calling addSelection() and notifyDataSetChanged().

    entityListFragment.setEntityListSelectListener(
      new EntityListFragment.OnItemSelectedListener() {
        public void onItemSelect(MyEntity entity) {
        aa.addSelection(entity);
        aa.notifyDataSetChanged(); }});
    
Christian Schulzendorff
  • 1,431
  • 1
  • 18
  • 15
2

I had the same problem, I solved it by pasting the following code in the ListView code

android:choiceMode="singleChoice"
android:listSelector="#003366"

The xml file looks as the following

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">

<ListView
    android:id="@+id/file_list"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:choiceMode="singleChoice"
    android:listSelector="#003366"/>

<Button
    android:id="@+id/select"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="SELECT"
    android:layout_below="@id/file_list"/>

</RelativeLayout>
Rijul Gupta
  • 1,045
  • 13
  • 20
1

In my case, when using simple_list_item_2, the only solution was to override the getView() method of the adapter, and just change the background color manually:

listview = new SimpleAdapter(ctx, data,
                android.R.layout.simple_list_item_2, res,
                new String[] {"field1", "field2" },
                new int[] {android.R.id.text1, android.R.id.text2 })

            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View view = super.getView(position, convertView, parent);

                if (this_is_the_selected_item)
                {
                    view.setBackgroundColor(0xff999999);
                }
                else
                {
                    view.setBackgroundColor(Color.BLACK);
                }
                return view;
            }
        };

Remember to call listview.invalidateViews() whenever you change the selected item.

CpnCrunch
  • 4,831
  • 1
  • 33
  • 31
0

Here's what I did :) - after major head whacking against wall.

For the adapter:

 radioAdapter = new RadioAdapter(context, R.layout.row_layout, yourData);

For the row_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/radio_name"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical"
android:padding="10dp"
android:background="?android:attr/activatedBackgroundIndicator"
android:clickable="true"
android:text="SOME RADIO"
android:textColor="@color/Gray"
android:textSize="25dp" />

To set a default position to be highlighted just do this to your listView object:

radioTitleList.setItemChecked(defaultPosition, true);

If you want highlighting when you click on the list:

In your getView() in your custom list adapter add this before returning the view:

 row.setOnClickListener(new OnClickListener() 
 {
 @Override
 public void onClick(View arg0) 
 {
     radioTitleList.setItemChecked(position, true);
             // other stuff like navigating to a new activity etc
     }
 });
shecodesthings
  • 1,218
  • 2
  • 15
  • 33