Drawable selector not working in Jelly Bean
Asked Answered
I

6

13

I have a drawable selector as a background for each item in a ListView to highlight the selected row. Eveything works fine in Ice Cream Sandwich, but doesn't seem to work in Jelly Bean. Can't find any documentation saying what changes could have caused it to stop working and what I need to do to fix it.

By not working, I mean when I click on a row in the ListView the item's background color isn't turning the @color/blue color, but it does in ICS.

This is the selector code I'm using (listing_selector.xml):

<selector xmlns:android="http://schemas.android.com/apk/res/android" >

   <item android:state_focused="true" android:drawable="@color/blue" />

   <item android:state_pressed="true" android:drawable="@color/blue" />

   <item android:state_activated="true" android:drawable="@color/blue_selected" />  

   <item android:state_selected="true" android:drawable="@color/blue_selected" />

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

</selector>

This is the layout of the ListView item:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"  
    android:layout_height="fill_parent" 
    android:orientation="horizontal"
    android:background="@color/listing_selector"    
>

    <TextView 
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true" 
    />

</RelativeLayout>

This the blue color resource:

<resources>
    <color name="blue">#ff33b5e5</color>       
</resources>

UPDATE 1:

Tried moving the selector from the color folder to the drawable folder and updating the code to this:

android:background="@drawable/listing_selector"

UPDATE 2:

Also, on the ListView, tried adding this:

    <ListView android:id="@android:id/list"
        android:layout_width="wrap_content"  
        android:layout_height="fill_parent" 
        android:listSelector="@drawable/listing_selector"   
    />

UPDATE 3:

I thought it might be something in my code, but I removed all the code from onListItemClick of the ListView and still the selector isn't working.

UPDATE 4:

I've narrowed it down to state_selected or state_activated not working as, state_pressed seems to be working

UPDATE 5:

I think I was mistaken. I don't think the selector is being recognized, at all. I was confusing the built-in ListView highlighting as my selector. I'm now wondering if it has something to do with the way my project is setup. I have the selector in a Library Class. Maybe something changed with that from ICS to JB, however moving the selector to my app's project didn't seem to fix it.

UPDATE 6:

Ok, after some more hair pulling, I've narrowed it down, again, to either state_selected or state_activated not being recognized, as changing the color for state_pressed does work, which means my selector is being recognized. From the comments in seems to be something with my app specifically as others have been able to get selectors working with Jelly Bean.

Though something else that is interesting is that changing the drawable value for the default state is not recognized. Where I have color/transparent, I would think changing that to a color would cause the listing to change to that color, but it doesn't.

Also, this isn't working in ICS either.

UPDATE 7:

After even more hair pulling, I've discovered that long-pressing on a menu item results in that item's color being changed. Just clicking on an item still does not work. Not even sure what the means.

** Final Update:**

I give up, I removed the selector and am just refreshing the ListView on click and remembering the position clicked and highlighting it from code. Not ideal, but not worth the effort to try to fix.

Inseparable answered 26/7, 2012 at 1:44 Comment(10)
When you tried your UPDATE 2, did you remove the android:background from your list item. I use android:listSelector for the list, and then no android:background is defined for the list item; and everything works for me. Also, I'm not sure if its related but I also have android:cacheColorHint="@null".Definitive
@Chris Yea, tried that didn't work either. I added a new update (#5). I'm wondering if the issue is with the way I have my project setup?Inseparable
Project setup should be unrelated to this issue assuming you have your android dependencies showing.... which eclipse basically forces you to do. Tip on the drawable vs color thing, use android:color for xml selectors in res/color,and android:drawable for xml selectors in res/drawable. For what you have there's probably no reason to use it as a drawable rather than a color. And colors implicitly have full opacity, so #ff33b5e5 is the same as #33b5e5Kally
What is your target version ? Try to put JellyBean as your sdk target in your project properties.Emancipated
I ran into the same issue, and ended up brute forcing like you did (making an exclusion for api17) by tracking which items were selected and setting their backgrounds under getView (which i was doing anyways for selecting items that are offscreen). Then calling notifyDataSetChanged() on the adapter under onListItemClick. Would be nice it this were clean, but it's not! I hope this gets fixed.Quitclaim
hello, did you find a solution, i am getting the same problem :( #14645017Standice
@haythemsouissi Never did find a solution. Still using the brute force method of manually selecting them item in the ListView unfortunately. I haven't heard of any complaints about it though, so it's a viable, though not ideal, solution.Inseparable
ok i fixed the issu of selected item, but still have the problem of dedecting when the item in the list is focused (or touched) can i get when an item in the list is touched?Standice
i got my answer here: https://mcmap.net/q/659232/-xml-background-don-39-t-change-when-i-use-tablet I think this may fix your problem too.Standice
Ah, I do have that value set. I'll have to try remove it. Thanks! I even forwarded this question to one of the Android on Google+ awhile ago, but didn't get a response. I knew it had to be some defect, because it didn't make any sense why it wasn't working.Inseparable
D
2

Okay, i think its an issue with your selector. Try removing the state_focused and the state_activated. You could try this for your selector:

<!-- Disabled State -->
<item
    android:state_enabled = "false"
    android:state_focused = "true"
    android:state_pressed = "true"
    android:drawable="@android:color/transparent">
</item>
<item
    android:state_enabled = "false"
    android:state_focused = "true"
    android:drawable="@android:color/transparent">
</item>

<!-- Pressed State -->
<item
    android:state_pressed = "true"
    android:state_focused = "true">
    <shape>
        <solid android:color="@color/blue"/>
    </shape>
</item>
<item
    android:state_pressed = "true"
    android:state_focused = "false">
    <shape>
        <solid android:color="@color/blue"/>
    </shape>
</item>

<!-- Normal State -->
<item
    android:drawable="@android:color/transparent">
</item>

I found that I needed to use a shape object too instead of android:drawable, because on pre-ICS phones, the whole list will be highlighted that color instead of the pressed list item.

You can add in your state_selected code too, but I'm not sure how it will be used. Check out the default selector code for jelly bean for the states they use: list_selector_background.xml.

Definitive answered 19/9, 2012 at 19:21 Comment(0)
C
1

listing_selector.xml must be in res/drawable folder and set the android:background attribute of your RelativeLayout like this:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"  
    android:layout_height="fill_parent" 
    android:orientation="horizontal"
    android:background="@drawable/listing_selector"    
>
Codee answered 26/7, 2012 at 2:27 Comment(6)
Moved the listing_selector.xml to the res/drawable folder, but still doesn't work.Inseparable
@KrisB K_Anas was emphasizing this line: @drawable/listing_selector.Bukavu
@SherifelKhatib not sure what you mean. I moved listing_selector.xml to res/drawable and changed that line of code to from android:background="@color/listing_selector" to android:background="@drawable/listing_selector". Am I missing something else?Inseparable
@KrisB well, I thought you missed that line (because of your comment). Can you try to remove this line and add listSelector to your ListView?Bukavu
@SherifelKhatib yep, tried that too, nada. I'll update my OP so it's moreo clear.Inseparable
@SherifelKhatib I've narrowed it down to state_selected or state_activated not working as, state_pressed seems to be workingInseparable
S
1

I cant say the reason why its working in one version and not working in another, but I got a alternative solution.

Define your color as a drawable in resources

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <drawable name="blue">#00F</drawable>
    ...
</resources>

Use this color drawable in your selector

<?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/blue" />
    ...
    ...
</selector>

Try this and let me know.

Speakeasy answered 19/9, 2012 at 10:13 Comment(0)
L
1

From the API Docs:

Note: Remember that Android applies the first item in the state list that matches the current state of the object. So, if the first item in the list contains none of the state attributes above, then it is applied every time, which is why your default value should always be last (as demonstrated in the following example).

Thus, try to reorder the states of your selectors according to the suggested order. In your case that would be this:

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
   <item android:state_pressed="true" android:drawable="@color/blue" />
   <item android:state_focused="true" android:drawable="@color/blue" />
   <item android:state_selected="true" android:drawable="@color/blue_selected" />
   <item android:state_activated="true" android:drawable="@color/blue_selected" />  
   <item android:drawable="@android:color/transparent" />
</selector>
Labrum answered 21/9, 2012 at 19:27 Comment(0)
C
0

I think it works fine !!

your selector xml file code:-

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

        <item android:drawable="@color/gray" android:state_focused="true"/>
        <item android:drawable="@color/gray" android:state_pressed="true"/>
        <item android:drawable="@color/orange" android:state_activated="true"/>
        <item android:drawable="@color/orange" android:state_selected="true"/>
        <item android:drawable="@color/orange"/>

    </selector>

now create a folder values-v16 under res folder and put this colors file in it.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <color name="gray">#4f4f4f</color>
    <color name="orange">#e26c0e</color>

</resources>

and then the listview :

<ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="20dp"
        android:listSelector="@drawable/listing_selector" >
</ListView>

Hope this works ! Tested on version 4.1

Chiles answered 20/9, 2012 at 12:19 Comment(2)
the only difference i found is i have placed the colors file under values-v16.Chiles
Thanks, there must be something wrong with the way my project is setup, so I'm thinking nothing changed in Jelly Bean. Still need to work through it though.Inseparable
M
0

This is a very old question but I am still supporting Jellybean and I've noticed for background selectors to work I need to do something in particular. If I have a viewgroup with a background drawable and I need selector colors on it I need to do things in this order:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/my_drawable_button"/>

my_drawable_button must now reference a selector:

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

primary_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="8dp" />
    <solid android:color="@color/secondary" />
</shape>

The others are the same with different colors. This is an awful lot of code to do something very basic, but I have found on Jellybean it's the only solution.

Future API levels allow you to specify the color selector on the drawable solid itself, eliminating 4 files:

post api 21:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/purple">
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="8dp" />
            <solid android:color="@color/button_selector" />
        </shape>
    </item>
</ripple>

button_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/gray" android:state_enabled="false"/>
    <item android:color="@color/secondary"/>
</selector>
Mg answered 23/6, 2022 at 16:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.