Spinner background with states not working - android

I am trying to set a custom background to the spinner:
<Spinner
android:id="#+id/spinner"
android:layout_width="wrap_content"
android:background="#drawable/spinner_bg"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/>
spinner_bg.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="#ff0000"/>
<item android:drawable="#00ff00"/>
</selector>
I saw a lot of tutorials and articles that are doing such thing, but in my case it
somehow doesn't work, I just got plain text without any states and backgorund, if I set color or 9-patch to the background all works fine. What am I doing wrong?
Edit: I have tried all suggestions, but it doesn't help, also Android Studio pointing out that something is wrong, but no hint available.
Edit2: I found the problem. I missed .xml extension for the spinner_bg file in my source. Also Mou had right correction that I should use drawable instead of color, so I marked his answer as correct.

The problem is in spinner_bg.xml.
android:drawable must be a reference to a drawable and not a color.
Try creating a shape drawable or another drawable (9-path) and setting it correctly in the xml.
EDIT:
Something like this:
spinner_bg_color.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#FFFF0000"/>
</shape>
And setting this drawable like background drawable in spinner_bg.xml

Change
android:drawable="#00ff00"
to
android:color="#00ff00"
like so:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:color="#ff0000"/>
<item android:color"#00ff00"/>
</selector>

Related

Changing Color State on an "ImageToggle" 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

Android spinner with underline appcompat

I am using a appcompat theme for my application. Need to know how i can show underline to spinner. It is just showing anchor. I tried setting up underline using android:background but it makes the anchor disappear.
Update your support library and in XML use
Please add this style to your Spinner
style="#style/Base.Widget.AppCompat.Spinner.Underlined"
This is hacky (and not perfect) way to change spinner and underline color in appcompat theme. Main point that I customized Android support library images and xml files to change color.
1) go to support library package and copy 2 images (or download my custom from the bottom of this post)
/your-app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.0/res/drawable-hdpi/abc_spinner_mtrl_am_alpha.9.png
and
/your-app/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.1.0/res/drawable-hdpi/abc_textfield_default_mtrl_alpha.9.png
2) Make a copy of those images
3) Change color of abc_spinner_mtrl_am_alpha.9.png (warning: leave black borders as they are, it's for 9 patch)
4) Change color of second bottom line of abc_textfield_default_mtrl_alpha.9.png (you can see in attached small image below)
5) Save and move files to your project drawables
6) Create bottom_line_color.xml drawable:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-6dp" android:left="-6dp" android:right="-6dp">
<shape>
<stroke android:color="#color/brown" android:width="6dp"/>
</shape>
</item>
7) Create spinner_bottom_line.xml
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="#dimen/abc_control_inset_material"
android:insetTop="#dimen/abc_control_inset_material"
android:insetBottom="#dimen/abc_control_inset_material"
android:insetRight="#dimen/abc_control_inset_material">
<selector>
<item android:state_checked="false" android:state_pressed="false">
<layer-list>
<item android:drawable="#drawable/my_custom_abc_textfield_default_mtrl_alpha" />
<item android:drawable="#drawable/my_custom_abc_spinner_mtrl_am_alpha" />
</layer-list>
</item>
<item>
<layer-list>
<item android:drawable="#drawable/my_custom_abc_textfield_default_mtrl_alpha" />
<item android:drawable="#drawable/my_custom_abc_spinner_mtrl_am_alpha" />
</layer-list>
</item>
</selector>
</inset>
P.S. I couldn't achieve same visual style as default spinner (visual changes shown below). If you start using this custom spinner theme you should use it in all project.
So add to values/styles.xml
<style name="My.Spinner.Style" parent="Base.Widget.AppCompat.Spinner.Underlined">
<item name="android:background">#drawable/spinner_bottom_line</item>
</style>
And use it in application like this:
<Spinner
android:id="#+id/account_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/My.Spinner.Style"
/>
Important:
You should resize spinner and place to various drawables folders. You can find size in same path as I showed above.
There are few popular sizes:
drawables-mdpi 20x26
drawables-hdpi 29x38
drawables-xhdpi 38x50
drawables-xxhdpi 74x98
You can take my customized images from here:
my_custom_abc_spinner_mtrl_am_alpha:
my_custom_abc_textfield_default_mtrl_alpha:
Spinner example is (xxhdpi), line is mdpi (because we don't need various lines in various drawable folders, so we can have only 1).
Visual difference (from android studio xml preview window) is shown here:
First line is my custom underline spinner, second is default Base.Widget.AppCompat.Spinner.Underlined
Applying style="#style/Base.Widget.AppCompat.Spinner.Underlined" didn't show any difference .Then gave android:backgroundTint and android:backgroundTintMode to spinner and it worked.
<Spinner
android:id="#+id/spBookingType"
android:spinnerMode="dropdown"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="#style/Base.Widget.AppCompat.Spinner.Underlined"
android:backgroundTint="#ff000000"
android:backgroundTintMode="src_in" />
in styles.xml
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:spinnerStyle">#style/holoSpinner</item>
</style>
<style name="holoSpinner" parent="Widget.AppCompat.Spinner.Underlined">
<item name="android:textSize">16sp</item>
<item name="android:textColor">#color/colorPrimary</item>
</style>
========================
in Layout
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<Spinner
android:id="#+id/spinCountry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/edit_text_bottom_border"
android:paddingBottom="10dp" />
</android.support.design.widget.TextInputLayout>
===============================================
edit_text_bottom_border.xml file in Drawable
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-3dp"
android:right="-3dp"
android:top="-3dp">
<shape android:shape="rectangle">
<stroke
android:width="1dp"
android:color="#535353" />
<!--android:color="#535353" />-->
</shape>
</item>
</layer-list>

Trouble with custom seekBar android

i have a trouble with custom seekBar .I used http://android-holo-colors.com/ to give images of seekBar .The problem is a vague beginning of seekBar . How can i solve this problem?!
ScreenShot:
this code (i check , images are the same as the default except for colors.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background"
android:drawable="#drawable/scrubber_track_red" />
<item android:id="#android:id/secondaryProgress">
<scale android:scaleWidth="100%"
android:drawable="#drawable/scrubber_secondary_red" />
</item>
<item android:id="#android:id/progress">
<scale android:scaleWidth="100%"
android:drawable="#drawable/scrubber_primary_red" />
</item>
</layer-list>
and SeekBar
<SeekBar
android:id="#+id/seekTrack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:progressDrawable="#drawable/scrubber_progress_red"
android:thumb="#drawable/scrubber_control_red"
android:indeterminate="false"
android:layout_weight="1"
style="?android:attr/progressBarStyleHorizontal"/>
Images i got from aforementioned service (android holo colors)
Check your drawables, there's probably a gradient in there somewhere as opposed to a solid color. I'd guess that the problem is in #drawable/scrubber_progress_red. Replace it temporarily with something like #android:color/holo_green_light. If the gradient goes away, we'll know that the scrubber_progress_red drawable is the problem.
Also, what is the name of the file that the layer-list is in?

Drawable selector not working in Jelly Bean

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>

Setting image source for ToggleButton

I have a 30px x 30px png file that i would like to use as an android:src rather than an android:background. By using it as the background, and mentioning "wrap_content" for both the height and the width, the final result looks more like a 45px x 45 px.
Ideally, what i need is a mix of ImageButton and ToggleButton. I would like to have the feature of setting an android:src of ImageButton and the feature of toggling where states are saved automatically for me.
Any solution or workaround?
TIA.
Hi, It does not seem to help creating another style. The src still appears much bigger that it's original 30px x 30px.
In main.xml:
<ToggleButton android:id="#+id/blah"
style="#style/myToggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</ToggleButton>
In Styles.xml
<style name="myToggle">
<item name="android:textOn">""</item>
<item name="android:textOff">""</item>
<item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
<item name="android:background">#drawable/my_btn_toggle_bg</item>
</style>
In my_btn_toggle_bg.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/myBackground" android:drawable="#android:drawable/btn_default_small" />
<item android:id="#+id/myToggle" android:drawable="#drawable/my_btn_toggle" />
</layer-list>
In my_btn_toggle.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="#drawable/pausebutton" />
<item android:state_checked="true" android:drawable="#drawable/playbutton" />
</selector>
playbutton.png and pausebutton.png are 30px x 30px each. But they appear much bigger when i see it laid out on the device
You can make the toggle button look like whatever you want. You just need to create a style. Have a look in the /platforms//data/res/values/styles.xml and search for Widget.Button.ToggleButton It looks like this:
<style name="Widget.Button.Toggle">
<item name="android:background">#android:drawable/btn_toggle_bg</item>
<item name="android:textOn">#android:string/capital_on</item>
<item name="android:textOff">#android:string/capital_off</item>
<item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
</style>
So if you go find the btn_toggle_bg drawable you find this:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+android:id/background" android:drawable="#android:drawable/btn_default_small" />
<item android:id="#+android:id/toggle" android:drawable="#android:drawable/btn_toggle" />
</layer-list>
Which shows you that it uses the standard Button background and a drawable called btn_toggle for the src. btn_src.xml looks like this:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="false" android:drawable="#drawable/btn_toggle_off" />
<item android:state_checked="true" android:drawable="#drawable/btn_toggle_on" />
</selector>
Which are the two drawables that are used to show the state of the button. They are actually called btn_toggle_{on/off}.9.png since they are 9 Patch images so they stretch to match the button size.
I figured out how to do this (centering a smaller background image inside a large ToggleButton) using ScaleDrawable:
Set your ToggleButton to use a selector Drawable, as normal:
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:variablePadding="true">
<item android:drawable="#drawable/ic_star_selected_centered"
android:state_checked="true" />
<item android:drawable="#drawable/ic_star_default_white_centered"
android:state_pressed="true" />
<item android:drawable="#drawable/ic_star_default_black_centered" />
</selector>
Then, make a ScaledDrawable for each of the items' drawables above, which points to your ACTUAL image file. e.g. ic_star_selected_centered.xml:
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="#drawable/ic_star_selected"
android:scaleGravity="center"
android:scaleHeight="100%"
android:scaleWidth="100%"
/>
Finally, there is a bug in Android that makes any ScaledDrawables invisible at first, until you set their level. So when inflating your view, call setLevel() from 1-10000 (1 is smallest scale, 10000 is full-sized):
StateListDrawable star = (StateListDrawable) myToggleButton.getBackground();
star.setLevel(5000); // centers the image at half size. shame on Android for using magic numbers!
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true">
<inset android:insetLeft="15dp" android:insetRight="15dp" android:insetTop="15dp" android:insetBottom="15dp">
<bitmap android:src="#drawable/ic_star_selected_centered" />
</inset>
</item>
<item android:state_pressed="true" >
<inset android:insetLeft="15dp" android:insetRight="15dp" android:insetTop="15dp" android:insetBottom="15dp">
<bitmap android:src=" android:src="#drawable/ic_star_default_white_centered" />
</inset>
</item>
<item >
<inset android:insetLeft="15dp" android:insetRight="15dp" android:insetTop="15dp" android:insetBottom="15dp">
<bitmap android:src="#drawable/ic_star_default_black_centered" />
</inset>
</item>
</selector>
In addition to what #caseyB had to say (look at the comments), i had to change the theme of the activity to achieve the intended effect. I think this is an issue on HoneyComb Xoom and may not be seen on phones.
Thanks for everyone for looking at my question and helping.
"Quick and dirty" way of achieving this is to use relative layout and place your ImageView on top of the ToggleButton. Set android:layout_centerInParent="true" and set your onClick listener on the toggle
Said that - the other solution by CaseyB (customizing background files) is the right approach

Categories

Resources