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.
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.
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"
>
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.
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>
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
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>
Related
I'm having an issue specific to Kitkat devices and lower, the code works exactly as expected on newer versions of Android. I'm styling a button using a selector, on Kitkat the color of the button is grey (#color/button_disabled_color), but on newer version the color is blue (?attr/colorPrimary). Can't Kitkat use the state correctly or is there something else going wrong here?
The selector looks like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/button_disabled_color" android:state_enabled="false" />
<item android:color="?attr/colorPrimary"/>
</selector>
The button is defined in xml as follows:
<android.support.v7.widget.AppCompatButton
android:id="#+id/buttonStandard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/standard_button"/>
The default button style is specified like below, note this style is set as the default style for buttons in the theme.
<style name="AppTheme.ButtonStyle" parent="Widget.AppCompat.Button.Colored">
<item name="backgroundTint">#color/primary_button_color</item>
<item name="android:textColor">#color/primary_button_text_color</item>
</style>
Note that it works fine for the textColor which is done in the exact same way. changing the ?attr/colorPrimary to an actual color specified in the colors.xml also made no difference.
Add selector like ..
square_blue.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="#android:integer/config_mediumAnimTime">
<item android:state_pressed="true" android:drawable="#drawable/square_blue_pressed"/>
<item android:drawable="#drawable/square_blue_normal"/>
</selector>
square_blue_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/light_blue" />
</shape>
square_blue_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/dark_blue" />
</shape>
in layout xml
<android.support.v7.widget.AppCompatTextView
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="20dp"
android:background="#drawable/square_blue"
android:text="#string/standard_button"/>
I currently have a set of ToggleButtons, enclosed by a RadioGroup, with each button referring to a selector that changes the color of the button state, and writing code to implement the radio-buttonesque behavior. This works great. (EDIT: I should mention that the selector is what the android:background element of the button is referred to)
The Selector is something like this
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/gold"
android:state_checked="true" />
<item android:drawable="#color/white" />
</selector>
Now I want a second set of buttons to have the exact same behavior. The catch is that this time, I want Images on some of them, not text.
There are lots of StackOverflow posts on how to change the Image based on the Button's state but I don't want to change the image based on the state. I want to change the color of the button based on the state (the images have transparent backgrounds).
I'm really trying to avoid modifying the button images themselves.
I believe the solution involves making a selector with a layer-list but this is new territory for me.
Create a xml named colors.xml in res/values folder:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="red">#ff0000</color>
<color name="green">#00ff00</color>
</resources>
In drawable folder, create a xml file my_btn_toggle.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="#color/red" />
<item android:state_checked="true" android:drawable="#color/green" />
</selector>
and in xml section define your toggle button:
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/btntoggle"
android:background="#drawable/my_btn_toggle"/>
I think you are looking for tinting attributes - mentioned here.
In your case, try to set ColoStateList to android:tint attribute. In ColorStateList doc you have example that shows color selector - like drawable selector, but for colors.
(I'm not sure it's already support pre-Lollipop devices or you should do it programatically with PorterDuff filters for older versions.)
What apparently one needs to do is create a layered drawable in the selector like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<layer-list>
<item android:drawable="#color/gold"
android:gravity="fill"/>
<item android:drawable="#drawable/image"
android:gravity="fill"/>
</layer-list>
</item>
<item android:state_checked="false">
<layer-list>
<item android:drawable="#color/white"
android:gravity="fill"/>
<item android:drawable="#drawable/image"
android:gravity="fill"/>
</layer-list>
</item>
</selector>
The standard approach to variable state button selectors is what Priyank mentions above. Just the graphic must be transparent and declared like above, such that it will be layered with a background color to pull off the color state change
I want to make a weekly calendar, where every day is a custom checkbox with objective to look like the image bellow:
(http://i.imgur.com/WjIKCd0.png)
When the user clicks on a day (Monday in this case), the "background" and "button" checkbox changes as well the text color...
I made the drawables and it seems to work fine... check bellow the code:
Checkbox layout:
<CheckBox
android:id="#+id/selectMonday"
android:layout_width="40dp"
android:layout_height="40dp"
android:button="#drawable/ic_none"
style="#style/CheckBoxBackgroundView"
android:onClick="selectDay"
android:text="#string/monday_letter"
android:gravity="center"
android:checked="true"/>
(the drawable "ic_none", is simple a 135x135 "transparent" image with nothing in it...)
Style (CheckBoxBackgroundView):
<style name="CheckBoxBackgroundView">
<item name="android:background">#drawable/background_day_week_picker_box_selector</item>
<item name="android:textColor">#color/text_color_day_week_picker_box_selector</item>
<item name="android:textSize">#dimen/text_spinner_text</item>
<item name="android:textStyle">bold</item>
</style>
Background Selector (background_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:drawable="#drawable/background_day_of_week_picker_unselected" />
<item android:state_checked="true"
android:drawable="#drawable/background_day_of_week_picker_selected" />
</selector>
Background selected (background_day_of_week_picker_selected):
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- view background color -->
<solid
android:color="#color/red_color" >
</solid>
<!-- view border color and width -->
<stroke
android:width="3dp"
android:color="#color/transparent">
</stroke>
<!-- Here is the corner radius -->
<corners
android:radius="10dp" >
</corners>
</shape>
and finally the color selector (text_color_day_week_picker_box_selector):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false"
android:color="#color/red_color"></item>
<item android:state_checked="true"
android:color="#color/white"></item>
</selector>
I tried this in several devices... in some, it appears like it suppose to, in others the text disappears and it looks like this:
(http://i.imgur.com/Jy9FrPS.png)
probably is coincidence, but all the devices that worked are below 5 inches...
is there anything wrong with my code that I'm not seeing? anyone have any suggestions?
Thanks in advance
The problem is that the 135x135 button drawable is pushing the text out of the bounds of your CheckBox's width. Instead of using a drawable, you can just set android:button="#color/transparent".
I use this for my own button to set the background for state pressed and unpressed:
<?xml version="1.0" encoding="utf-8"?>
<item android:drawable="#drawable/btn1_pressed" android:state_pressed="true"/>
<item android:drawable="#drawable/btn1_unpressed"/> <!-- default -->
But I also like the textColor to become white in state pressed.
I tried to just add textColor="#ffffff" to the item but I guess that's not the correct way, since it did not work.
What would be the best approach without having to code it in each java file that uses this button?
Thanks!
The best is to set Textcolor and Background resource separate.
android:background="#drawable/background"
android:textColor="#drawable/button_text_color"
so your Background: as you wrote it yourself
and Textcolor:
<?xml version="1.0" encoding="UTF-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#ffffffff" />
<item android:color="#ff000000" />
</selector>
I am struggling with this which apparently is a very simple effect but incredibly haven't found any intutitive way for doing it in Android.
I have a ListView and I managed to customize the background images so the selected item gets highlighted by getting a new background drawable. This I do creating a new style where I set the android:listSelector attribute to point a StateListDrawable where I have specified which drawables to use for every state.
However each ListView item is a LinearLayout where i have two TextViews. My goal is to be able to change the text color of these child views whenever the parent is selected or pressed, at the same time as the background drawable does. I know there is a ColorStateList but haven't been succesful setting that up.
Has anybody succeed getting something like this to work?
Thanks.
Neither of these are possible answers when your ListView is compromised of a layout that has multiple views. You need to set your child views to:
android:duplicateParentState="true"
Now you can use the methods others have described above to declare your TextViews' colors using a selector such as:
android:textColor="#drawable/my_row_selector"
and I'm sure you're aware, but the selector can be as simple as:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#color/white" />
<item android:color="#color/black" />
</selector>
As you can see, #color values are allowed. Hope this helps.
Also - android:state_pressed is used in conjunction with the AdapterView.OnItemClickListener.
in your textview propeties
android:textColor="#color/text_selector"
in res/color
text_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="YOUR_CUSTOM_COLOR" />
<item android:state_selected="true" android:color="YOUR_CUSTOM_COLOR" />
<item android:color="YOUR_CUSTOM_COLOR" />
</selector>
In order to make it work on selection use the following code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#fff"/>
<item android:state_activated="true" android:color="#fff"/>
<item android:color="#000" />
</selector>
Apparently the key is state_activated="true" state.
When you are deploying the app for Android 11+ (HoneyComb+), you should use
android:state_activated="true"
for selected list state.
For the earlier versions use the combination of:
android:state_checked="true"
android:state_activated="true"
Of course don't forget to include the
android:duplicateParentState="true"
so the view can get the activated/checked state from a parent list view item
Also you may create a res/color folder and add a file "text_selector.xml" with the following lines:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_activated="true" android:color="#f0f"/>
<item android:state_pressed="true" android:color="#f0f"/>
<item android:color="#000"/>
</selector>
After that assign in TextView:
android:textColor="#color/text_selector"