64

I want to know on how I can change the background color of the selected item on my listView. I only want to change the specific item clicked by the user, meaning if the user clicks another item it will be the one which is highlighted. Well since I want it to keep simple as possible and use the default android listview I used this code instead:

record_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                try{
                    for (int ctr=0;ctr<=record_items.length;ctr++){
                        if(i==ctr){
                            record_list.getChildAt(ctr).setBackgroundColor(Color.CYAN);
                        }else{
                            record_list.getChildAt(ctr).setBackgroundColor(Color.WHITE);
                        }
                    }
                }
                catch (Exception e){
                    e.printStackTrace();
                }
                Log.v("Selected item",record_list.getItemAtPosition(i));
            }
        });

Ok this one is working but the problem is that it's slow. Now I want to know if there's any other way around that I can do which will give the same output as I made.

I tried using record_list.getSelectedView().setBackgroundColor(Color.CYAN); but it gives me a null pointer exception.

I also tried the selector.xml but it also didn't do the trick. Furthermore, there is one properties here on ListView which is called listSelector. It's a drawable as said by the documentation "Drawable used to indicate the currently selected item in the list." I also believe that this should do the trick and yes it do the trick on my emulator but not on my galaxy tab. I also tried the other methods but nothing works as I wanted it to be.

KaHeL
  • 4,301
  • 16
  • 54
  • 78
  • 1
    use xml file for listview for that.. – Sagar Maiyad Jun 07 '13 at 04:53
  • have you checked this option, list.setSelector(R.drawable.detail_hover); where my deatil_hover is the .png drawable. try this i hope this will help you. – Anuj Sharma Jun 07 '13 at 05:07
  • you get view object in onitem click, so change the background color of that view and save it as prvsselected view on next click check prvsselect view is null or not, if it is not null then change its color to default one – OMAK Jun 07 '13 at 06:03
  • 1
    This method will fail for lists larger than 1 screen height. – Taochok May 16 '16 at 05:42
  • Effective solution in 2 lines: http://stackoverflow.com/questions/16976431/change-background-color-of-selected-item-on-a-listview/37248223#37248223 – Taochok May 16 '16 at 07:03
  • You can pick something from all of the answers here and piece a beautiful solution. – SubqueryCrunch Jan 25 '20 at 19:57

17 Answers17

84

You can keep track the position of the current selected element:

    OnItemClickListener listViewOnItemClick = new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adapter, View arg1, int position, long id) {
                mSelectedItem = position;
                mAdapter.notifyDataSetChanged();
        }
    };

And override the getView method of your adapter:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final View view = View.inflate(context, R.layout.item_list, null);

        if (position == mSelectedItem) {
            // set your color
        }

        return view;
    }

For me it did the trick.

Esteam
  • 1,911
  • 1
  • 16
  • 24
  • 2
    You should just have to set view.setSelected(true) in the onItemClick listener: http://stackoverflow.com/questions/16189651/android-listview-selected-item-stay-highlighted – ssawchenko Sep 25 '13 at 23:16
  • 13
    Esteam's solution is correct. The problem with only using view.setSelected(true) is that those views are recycled. As soon as you have a list large enough to scroll, this will no longer work. – TMLZ77 Jun 13 '14 at 19:25
  • 1
    For me I had to use `id` instead of `position` because `position` starts at 1 while the items in my adapter start at 0. I may be a rare case for this though, but figured I'd mention it in case anyone gets stuck. – CodyEngel Apr 21 '15 at 17:56
  • @HuskyHuskie Isn't that because you have a header view? I always use `position` and extract the header view count. – NecipAllef Oct 08 '15 at 05:13
  • 2
    This will break up in Lollypop - if you set a background on an item, you no longer see those fancy click animations. – elcuco Oct 08 '15 at 11:56
  • If the view is not recycled the background will stay if you set another item as selected. I discovered this on CAT S50 – Pwnstar Jul 11 '16 at 16:28
  • where to hold `mSelectedItem` variable? adapter and activity are different classes – ibubi Jun 15 '20 at 18:32
72

You can use a selector. Change the colors values and modify the below according to your needs.

bkg.xml in drawable folder

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" 
    android:drawable="@drawable/pressed" />
<item  android:state_focused="false" 
    android:drawable="@drawable/normal" />
</selector>

pressed.xml in drawable folder

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
<solid android:color="#FF1A47"/>  // color   
<stroke android:width="3dp"
        android:color="#0FECFF"/> // border
<padding android:left="5dp"
         android:top="5dp"
         android:right="5dp"
         android:bottom="5dp"/> 
<corners android:bottomRightRadius="7dp" // for rounded corners
         android:bottomLeftRadius="7dp" 
         android:topLeftRadius="7dp"
         android:topRightRadius="7dp"/> 
</shape>

normal.xml in drawable folder

<?xml version="1.0" encoding="UTF-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android"> 
<solid android:color="#FFFFFF"/>    
<stroke android:width="3dp"
        android:color="#0FECFF" />

<padding android:left="5dp"
         android:top="5dp"
         android:right="5dp"
         android:bottom="5dp"/> 
<corners android:bottomRightRadius="7dp"
         android:bottomLeftRadius="7dp" 
         android:topLeftRadius="7dp"
         android:topRightRadius="7dp"/> 
</shape>

Set the background drawable to listview custom layout to be inflated for each row

I recommend using a custom listview with a custom adapter.

  android:background="@drawable/bkg"     

If you have not used a custom adapter you can set the listselector to listview as below

   android:listSelector="@drawable/bkg" 
arlomedia
  • 8,534
  • 5
  • 60
  • 108
Raghunandan
  • 132,755
  • 26
  • 225
  • 256
  • i have try this code,but when i click list item its color change for few seconds only,what if i want to show item as selected. – Ravi Bhandari Feb 05 '14 at 12:37
  • @rb16 that is what selectors are for. If not you are looking for a different solution not this – Raghunandan Feb 05 '14 at 12:37
  • 6
    Currently when i click on a list item its color change while it pressed after release its color change to default color.But my requirement is that i want to show clicked item as selected until i don't click on other list item – Ravi Bhandari Feb 05 '14 at 13:06
  • In order to have the an item selected, add an entry for `state_selected="true"` to the selector xml. – jazzgil Apr 22 '17 at 15:40
  • just changing background color requires 3 more xml files. omg... – chmin.seo Dec 04 '19 at 07:55
  • @chmin - no, you can do it in one file. The reason things are split into multiple files is to reuse them in other places ie. code reuse, and a single place to change one value and have it affect everything instead of wanting to change things later and having to change it in 20 different places (and forgetting one). Just look up selectors and you are bound to find one that is in a single file. – LordWabbit Jul 09 '20 at 08:18
33

Define variable

private ListView mListView;

Initialize variable

mListView = (ListView)findViewById(R.id.list_view);

OnItemClickListener of listview

   mListView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?> adpterView, View view, int position,
                long id) {
            for (int i = 0; i < mListView.getChildCount(); i++) {
                if(position == i ){
                    mListView.getChildAt(i).setBackgroundColor(Color.BLUE);     
                }else{
                    mListView.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
                }
            }
        }
    });

Build and run the project - Done

Hiren Patel
  • 52,124
  • 21
  • 173
  • 151
  • Hi, your answer is almost the same as the one I've tried to implement which is not working the way I wanted it. Also this question has been answered and accepted for almost two years ago. :) – KaHeL May 06 '15 at 07:12
  • 1
    @KaHeL, thanks for sharing concern, I have tried above and other solutions but I could not get proper result so I tried it with my own solution, fortunately it's work for me. Thanks – Hiren Patel May 06 '15 at 15:36
  • 1
    This one works! This solution worked for me and the others didn't. I added this "for" statement to my navigation drawer right after the line "selectItem( position );" and now it works like a charm. Upvoted! I need to explain why this one worked : the otherS left the option selected, so, after selecting another, there were two options selected, this solution changes the colors of all options and only one stays with desired color. – Jose Manuel Abarca Rodríguez Jun 05 '15 at 15:54
  • @JoseManuelAbarcaRodríguez, glad to help you and thanks for appreciation. :) – Hiren Patel Jun 05 '15 at 17:34
  • 3
    Be careful, if the list goes longer than one screen height, it will crush with a null pointer. In addition, if you have a list with thousands of items, it will go one after one when you only see a few. – Taochok May 16 '16 at 05:06
  • You are d man...this is the simplest and most understandable solution I've ever seen. +1 for that... –  Oct 11 '16 at 13:45
16

If you want to have the item remain highlighted after you have clicked it, you need to manually set it as being selected in the onItemClick listener

Android ListView selected item stay highlighted:

myList.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {   
        view.setSelected(true); // <== Will cause the highlight to remain
        //... do more stuff                          
    }});

This assumes you have a state_selected item in your selector:

<?xml version="1.0" encoding="utf-8"?>
  <selector xmlns:android="http://schemas.android.com/apk/res/android">  
  <item android:state_enabled="true" android:state_pressed="true" android:drawable="@color/red" />
  <item android:state_enabled="true" android:state_focused="true" android:drawable="@color/red" />
  <item android:state_enabled="true" android:state_selected="true" android:drawable="@color/red" />
  <item android:drawable="@color/white" />
</selector>
Community
  • 1
  • 1
ssawchenko
  • 1,198
  • 1
  • 13
  • 24
  • The `view.setSelected(true);` makes my item be always selected. How can I make it not selected? – Sonhja May 07 '15 at 08:23
  • 1
    @Sonhja you should make every item by default unselected every time and check in getView if that is equal to selected position then make is selected true else false – Akhil Dad May 21 '15 at 03:26
12

Method 1:

Update ListView in the your xml layout activity/fragment:

<ListView
   ...
   android:choiceMode="singleChoice"
   android:listSelector="@android:color/darker_gray"
/>

That's it, you're done!

If you want a programmatic way to handle this then use method 2...

Method 2:

If you're using a ListFragment you can override onListItemClick(), using the view to set the colour. Save the current View selected to reset the colour of the last selection.

Please note, this only works on listviews that fit on one screen, as the view is recycled.

public class MyListFragment extends ListFragment {
    View previousSelectedItem;
...
    @Override
    public void onListItemClick(ListView parent, View v, int position, long id) {
        super.onListItemClick(parent, v, position, id);
        if (previousSelectedItem!=null) {
            previousSelectedItem.setBackgroundColor(Color.WHITE);
        }
        previousSelectedItem=v;
        v.setBackgroundColor(Color.BLUE);
    }
}
JMax
  • 647
  • 6
  • 8
7

First you can create selector xml file like below in your drawable folder drawable/list_item_selector.xml

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

    <item android:state_activated="true">
      <shape android:shape="rectangle">
        <solid android:color="#333333" />
        <padding android:left="5dp" android:right="5dp" />
      </shape></item>
    <item><shape android:shape="rectangle">
            <solid android:color="#222222" />
        </shape></item>

</selector>

And then in your listview specify background as

android:background="@drawable/list_item_selector"
Nirali
  • 13,571
  • 6
  • 40
  • 53
7

For those wondering what EXACTLY needs to be done to keep rows selected even as you scroll up down. It's the state_activated The rest is taken care of by internal functionality, you don't have to worry about toggle, and can select multiple items. I didn't need to use notifyDataSetChanged() or setSelected(true) methods.

Add this line to your selector file, for me drawable\row_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@android:color/holo_blue_light"/>

    <item android:state_enabled="true" android:state_pressed="true" android:drawable="@android:color/holo_blue_light" />
    <item android:state_enabled="true" android:state_focused="true" android:drawable="@android:color/holo_blue_bright" />
    <item android:state_enabled="true" android:state_selected="true" android:drawable="@android:color/holo_blue_light" />
    <item android:state_activated="true" android:drawable="@android:color/holo_blue_light" />

    <item android:drawable="@android:color/transparent"/>
</selector>

Then in layout\custom_row.xml

<?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dip"
        android:background="@drawable/row_background"
        android:orientation="vertical">
  <TextView
        android:id="@+id/line1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

For more information, I'm using this with ListView Adapter, using myList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); and myList.setMultiChoiceModeListener(new MultiChoiceModeListener()...

from this example: http://www.androidbegin.com/tutorial/android-delete-multiple-selected-items-listview-tutorial/

Also, you (should) use this structure for your list-adapter coupling: List myList = new ArrayList();

instead of: ArrayList myList = new ArrayList();

Explanation: Type List vs type ArrayList in Java

Community
  • 1
  • 1
Emil
  • 589
  • 6
  • 7
  • Thanks for your answer. – Chirag Savsani Mar 17 '17 at 06:16
  • Hi Emil, with your solution is it possible to deselect the item programmatically? – Sam Jun 22 '17 at 07:13
  • Hi @Sam my solution is based on the example I linked. It's a very good ListView tutorial after which you pretty much gain understanding of how the Lists works and how the code interacts with XML files. You have to know all the info presented there, it's too fundamental to skip this, and that tutorial is straight to the point. I went through a few others but their presentation was too confusing or misleading so discarded them midway. Once that works "automatically" Try this for programmatic approach: https://stackoverflow.com/questions/10788688/programmatically-select-item-listview-in-android – Emil Jun 27 '17 at 13:16
6

Simplest way I've found:

in your activity XML add these lines:

<ListView 
... 
android:choiceMode="singleChoice"
android:listSelector="#666666"
/>

or programatically set these properties:

listView.setSelector(Drawable selector)
listView.setSelector(int resourceId)

My particular example:

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

thanks to AJG: https://stackoverflow.com/a/25131125/1687010

Community
  • 1
  • 1
Taochok
  • 359
  • 4
  • 7
4
View updateview;// above oncreate method
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);


listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
         if (updateview != null) 
            updateview.setBackgroundColor(Color.TRANSPARENT);
         updateview = view;   

         view.setBackgroundColor(Color.CYAN);
     }
});
Alp Altunel
  • 3,324
  • 1
  • 26
  • 27
nandish
  • 41
  • 4
  • this is the easiest i can find. only one item will remain highlighted and as soon as you select another element in the list. the previous one will be automatically gets deselected – nandish Jul 15 '16 at 22:36
  • What does your answer offer over the already accepted answer? – Mario Tacke Jul 15 '16 at 23:01
3

I'm also doing the similar thing: highlight the selected list item's background (change it to red) and set text color within the item to white.

I can think out a "simple but not efficient" way: maintain a selected item's position in the custom adapter, and change it in the ListView's OnItemClickListener implement:

// The OnItemClickListener implementation
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    mListViewAdapter.setSelectedItem(position);
}

// The custom Adapter
private int mSelectedPosition = -1;
public void setSelectedItem (int itemPosition) {
    mSelectedPosition = itemPosition;
    notifyDataSetChanged();
}

Then update the selected item's background and text color in getView() method.

// The custom Adapter
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ...
    if (position == mSelectedPosition) {
        // customize the selected item's background and sub views
        convertView.setBackgroundColor(YOUR_HIGHLIGHT_COLOR);
        textView.setTextColor(TEXT_COLOR);
    } else {
        ...
    }
}

After searching for a while, I found that many people mentioned about to set android:listSelector="YOUR_SELECTOR". After tried for a while, I found the simplest way to highlight selected ListView item's background can be done with only two lines set to the ListView's layout resource:

android:choiceMode="singleChoice"
android:listSelector="YOUR_COLOR"

There's also other way to make it work, like customize activatedBackgroundIndicator theme. But I think that would be a much more generic solution since it will affect the whole theme.

Ethan Zhong
  • 91
  • 1
  • 2
2

use the below xml as listitem background it will solve all the issues. The selected will be highlighted though you scrolled down.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/holo_orange_dark" android:state_pressed="true"/>
<item android:drawable="@android:color/holo_green_light" android:state_selected="true"/>
<item android:drawable="@android:color/holo_green_light" android:state_activated="true"/>

Thanks, Nagendra

  • Hi Nagendra, with your solution is it possible to deselect the item programmatically? – Sam Jun 22 '17 at 07:14
2

I know this is a old question, but i give a simple solution for this need (without loops!):

//On your adapter create a variable:
private View lastSelectedItem;

//Define the folowing method:
private void toggleBackgroundItem(View view) {
    if (lastSelectedItem != null) {
        lastSelectedItem.setBackgroundColor(Color.TRANSPARENT);
    }
    view.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
    lastSelectedItem = view;

}
//finally invoque the method onItemClick
lvSac.setOnItemClickListener(new AdapterView.OnItemClickListener()

{
    @Override
    public void onItemClick (AdapterView < ? > adapterView, View view,int i, long l){

    toggleBackgroundItem(view);
}
}
Daniel Amaral
  • 126
  • 1
  • 5
2

In a ListView set:

android:choiceMode="singleChoice"

Create a selector for a background (drawable/selector_gray.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/gray" android:state_checked="true" />
    <item android:drawable="@color/white" />
</selector>

Add an item for a list:

<?xml version="1.0" encoding="utf-8"?>
<TextView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:padding="5dp"
    android:background="@drawable/selector_gray"
    android:textColor="@color/colorPrimary"
    tools:text="Your text" />

In a ViewHolder you can inflate this item.

CoolMind
  • 26,736
  • 15
  • 188
  • 224
  • 1
    I changed the "android:state_checked" to "android:state_selected" and when I call view.setSelected(true) in onItemClickedListener of my list view, it works. – civic.LiLister Jul 30 '20 at 17:19
  • @civic.LiLister, thanks, this is a good point. I think, it can depend on list items. But agree, your variant is more helpful and more often used. – CoolMind Jul 30 '20 at 19:14
2

nameofList.getChildAt(position).setBackgroundColor(RED);

worked for me

Vee Lad
  • 31
  • 4
1

assume you want one item to be clicked each time. Then this code works well. Let's take the listview name as stlist

stList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        // here i overide the onitemclick method in onitemclick listener
            public void onItemClick(AdapterView<?> parent, View view,
                                int position, long id) {

            //color change
            //selected item colored

            for(int i=0; i<stList.getAdapter().getCount();i++)
            {
                stList.getChildAt(i).setBackgroundColor(Color.TRANSPARENT);
            }

            parent.getChildAt(position).setBackgroundColor(Color.GRAY);

    });
Miraj Hamid
  • 554
  • 10
  • 19
  • 2
    Be careful, if the list goes longer than one screen height, it will crush with a null pointer. In addition, if you have a list with thousands of items, it will go one after one when you only see a few. – Taochok May 16 '16 at 05:07
1

This is a simple method that can handle selection even if the list is long as well:

public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    Holder holder=new Holder();
    View rowView;
    rowView = inflater.inflate(R.layout.list_item, null);
    //Handle your items.
    //StringHolder.mSelectedItem is a public static variable.
    if(getItemId(position)==StringHolder.mSelectedItem){
        rowView.setBackgroundColor(Color.LTGRAY);

    }else{
        rowView.setBackgroundColor(Color.TRANSPARENT);
    }
    return rowView;
}

And then in your onclicklistener:

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            StringHolder.mSelectedItem = catagoryAdapter.getItemId(i-1);
            catagoryAdapter.notifyDataSetChanged();
.....
0

It's very simple. In the constructor of the "OnItemClick" use the parameter "view" which is the second one that represents the listView or GridView's items's view and it becomes the new item's view made by the adapterView it self. So to set new color ONLY to the SELECTED ITEM itself do as the following:

public void onItemClick(AdapterView<?> adapterView, View view, int i, long l){ //view is instead of the view like textView , ImageView, or whatever view.setBackgroundColor(Color.green); }

If you do any different codes to set new color, you will face awkward behaviours like the green color will be applied to the unclicked item.