I tried to track down, how Lollipop displays a button, which is disabled with android:enabled="false" in the layout file.
Holo
With Holo, it's easy: In the styles_holo.xml, I find the style Widget.Holo.Button, which gives me a reference to #drawable/btn_default_holo_dark. There I find the selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_window_focused="false" android:state_enabled="true"
android:drawable="#drawable/btn_default_normal_holo_dark" />
<item android:state_window_focused="false" android:state_enabled="false"
android:drawable="#drawable/btn_default_disabled_holo_dark" />
<item android:state_pressed="true"
android:drawable="#drawable/btn_default_pressed_holo_dark" />
<item android:state_focused="true" android:state_enabled="true"
android:drawable="#drawable/btn_default_focused_holo_dark" />
<item android:state_enabled="true"
android:drawable="#drawable/btn_default_normal_holo_dark" />
<item android:state_focused="true"
android:drawable="#drawable/btn_default_disabled_focused_holo_dark" />
<item
android:drawable="#drawable/btn_default_disabled_holo_dark" />
</selector>
Lollipop
When I try to apply the same logic to Lollipop, I got stuck:
In styles_material.xml I find the style <style name="Widget.Material.Button"> where I find the reference to <item name="background">#drawable/btn_default_material</item>. But there is no selector??!! Instead I find:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:drawable="#drawable/btn_default_mtrl_shape" />
</ripple>
Could someone please explain, which specific style Lollipop uses for a disabled button.
Thanks a lot!
Edit
I can partially answer myself: In #drawable/btn_default_mtrl_shape I find a reference to <solid android:color="?attr/colorButtonNormal" />, which in turn points to #color/btn_default_material_light, which includes a selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:alpha="#dimen/disabled_alpha_material_light"
android:color="#color/button_material_light"/>
<item android:color="#color/button_material_light"/>
</selector>
But that alpha value only explains half of it. Somehow Lollipop also set the elevation down to 0?
This is how I resolved this, thanks to your partially answer.
First: add new Folder "color" under "res" folder, if it doesn`t exist.
Add new .xml file in "color" folder (I will call this file ButtonColorSelector.xml) where we will create new ColorStateList like this:
<?xml version="1.0" encoding="UTF-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="#F2F2F2"/> <!-- disabled -->
<item android:state_pressed="true" android:color="#FF0000"/> <!-- pressed -->
<item android:state_focused="true" android:color="#FF0000"/> <!-- focused -->
<item android:color="#0000FF"/> <!-- default -->
</selector>
Second: Add that ripple effect .xml file you mentioned, under "drawable" folder and reference your colorSelector instead of btn_default_mtrl_shape. I will call this file RaisedButton.xml.
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item>
<shape>
<solid android:color="#color/buttoncolorselector"/>
<corners android:radius="5dp" />
</shape>
</item>
</ripple>
Third: Now you can use your drawable for button background in your layouts, like this:
<Button
android:background="#drawable/raisedbutton"
android:text="#string/SomeButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="DoStuffitto"
android:enabled="false"
android:id="#+id/someButton" />
Related
i'm trying to make a simple rounded button like this
starting from this
The problem is that i don't want to lose the style (the ripple and the color change when you press it and the shadow). that would happen using a state-drawable as background.
How can i achieve it?
Just use the MaterialButton in the Material Components library with the app:cornerRadius attribute.
Something like:
<com.google.android.material.button.MaterialButton
android:text="NORMAL"
app:cornerRadius="16dp"
../>
<android.support.v7.widget.AppCompatButton
style="#style/buttonApp"
android:text="Normal" />
in res>values>styles.xml put this. and change padding, colors if you need.
<style name="buttonApp" parent="#style/Widget.AppCompat.Button.Borderless">
<item name="android:layout_height">#dimen/appButtonHeight</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:gravity">center</item>
<item name="android:paddingLeft">20dp</item>
<item name="android:paddingRight">20dp</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="android:textColor">#color/colorWhite</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">16sp</item>
<item name="android:background">#drawable/bg_button_orange</item>
</style>
You will get required press effect by 1 drawable for post 21 version, like below, but pre 21 version do not support ripple effect so you have to make some drawables background for press and non press effect, i have included final solution here
bg_button_orange.xml in res>drawables-v21>
(this is after 21 version android)
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="#android:id/mask">
<shape android:shape="rectangle">
<solid android:color="#color/colorGreenAlpha" />
<corners android:radius="15dp" />
</shape>
</item>
<item android:drawable="#drawable/bg_button_not_selected" />
</ripple>
bg_button_orange.xml in res>drawables>
(this is for pre 21 version android)
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/bg_button_selected" android:state_pressed="true" />
<item android:drawable="#drawable/bg_button_selected" android:state_focused="true" />
<item android:drawable="#drawable/bg_button_selected" android:state_selected="true" />
<item android:drawable="#drawable/bg_button_not_selected" />
</selector>
bg_button_not_selected.xml in res>drawables
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/colorGreenLight" />
<corners android:radius="#dimen/appButtonRadius" />
</shape>
bg_button_not_selected.xml in res>drawables
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/colorGreen" />
<corners android:radius="#dimen/appButtonRadius" />
</shape>
put in res>values>dimens.xml
<dimen name="appButtonHeight">60dp</dimen>
<dimen name="appButtonRadius">30dp</dimen>
put in res>values>colors.xml
<color name="colorGreen">#009688</color>
<color name="colorGreenAlpha">#b0009688</color>
<color name="colorGreenLight">#27d4c4</color>
Button height should be double than button radius to get exact round corners.
You will get button like belo image with ripple effect on post 21 version and press effect before 21 version.
I have a simple Button, which has a drawable set as icon:
<Button
android:id="#+id/bOk"
android:drawableStart="#drawable/icon_ok"
android:text="#string/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
when I disable the button, either in XML layout file: android:enabled="false"
or programmaticaly: bOk.setEnabled(false);
The button gets disabled, it is 'grayed out', but the icon remains as it was ine the enabled state.
How can I get a look, that the icon is also 'grayed out'?
Create a new grayed icon and add both inside a selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/icon_ok" android:state_enabled="true" />
<item android:drawable="#drawable/icon_ok_disabled" android:state_enabled="false" />
</selector>
Use inside button like: android:drawableStart="#drawable/selector"
For TextColor,
Create another selector inside res/color/mycustomtextcolor.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#666" android:state_enabled="false" />
<item android:color="#000" android:state_enabled="true"/>
</selector>
Inside your widget call using: android:textColor="#color/mycustomtextcolor"
Or
inside your style add another item using: <item name="android:textColor">#color/mycustomtextcolor</item>
Like a regular Button, a Button that has an image background is not grayed when disabled.
You have to use another image it appears grayed.
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false"
android:drawable="#drawable/button_gray" /> ***button_gray is a Drawable image***
<item android:state_pressed="true"
android:drawable="#drawable/button_gray" />
<item android:drawable="#drawable/button_red" /> ***button_red is a Drawable image***
</selector>
You can tint your drawable on enabled and disabled state using a selector with bitmaps:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false">
<bitmap android:src="#drawable/icon_ok" android:tint="#color/disableColorWithAlpha" />
</item>
<item android:state_enabled="true">
<bitmap android:src="#drawable/icon_ok" android:tint="#color/colorAccent" />
</item>
</selector>
I am using the Xamarin sample at the following link:
Part 3 - Customizing a ListView's Appearance
The sample code is from the following file: CustomRowView.zip
Here is a screenshot of my running code: Emulator screenshot
The background color of the ListView items are in yellow.
May I please have some help to change this color to be the default color, or to choose this color?
I am not sure where to find this in code. I have looked in the XML layout files, but cannot find the correct item.
In the RelativeLayout, there is a reference to the following:
android:background="#drawable/CustomSelector"
And this is the contents of the file:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false"
android:state_selected="false"
android:drawable="#color/cellback" />
<item android:state_pressed="true" >
<shape>
<gradient
android:startColor="#E88A93"
android:endColor="#E88A93"
android:angle="270" />
</shape>
</item>
<item android:state_selected="true"
android:state_pressed="false"
android:drawable="#color/cellback" />
</selector>
Is this code relevant to the question?
Thanks in advance
The "yello background color" is the custom listview item's background color. In the toturial you referenced, you can find it in "/Resources/Layout/CustomView.axml" :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#FFDAFF7F"
android:padding="8dp">
<LinearLayout android:id="#+id/Text"
android:orientation="vertical"
...
...
android:layout_height="48dp"
android:padding="5dp"
android:src="#drawable/icon"
android:layout_alignParentRight="true"
/>
</RelativeLayout >
the android:background="#FFDAFF7F" is what you want to modify.
Your ListView is using CustomView.axml for each row. in CustomView.axml parent element (RelativeLayout) is using CustomSelector.xml from Drawable folder in android:background attribute. In this file you can change colors of three states (pressed, pressed & selected, none) as you wish.
Create a color.xml in your values file and defines your color(which color you wnt to set to your listview ite) here
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="magenta">#FF00FF</color>
<color name="yellow">#FFFF00</color>
<color name="light_grey">#ffb9b8bb</color>
</resources>
and then use these colors in your custom selector
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/light_grey" android:state_pressed="false" android:state_selected="false"/>
<item android:state_pressed="true"><shape>
<gradient android:angle="270" android:endColor="#E88A93" android:startColor="#E88A93" />
</shape></item>
<item android:drawable="#color/light_grey" android:state_pressed="false" android:state_selected="true"/>
</selector>
I never get it yellow, which should come after pressing an item in the list.
(I changed your sample to yellow for state_pressed=true.
Tks
Seli
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/light_grey" android:state_pressed="false" android:state_selected="false"/>
<item android:state_pressed="true">
<shape>
<gradient android:angle="270" android:endColor="#E88A93" android:startColor="#E88A93" />
</shape>
</item>
<item android:drawable="#color/yellow" android:state_pressed="false" android:state_selected="true"/>
</selector>
For example, say I have a color state list declared in XML, called example1.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="#color/red"
android:state_pressed="true" />
<item
android:color="#color/blue"
android:state_checked="true" />
<item
android:color="#color/green"
android:state_disabled="true" />
<item
android:color="#color/orange" />
</selector>
Then, I want to create example2.xml and I want it to be the exact same as example1.xml except I want the pressed color to be purple instead of red:
<item
android:color="#color/purple"
android:state_pressed="true" />
So example2.xml would end up acting like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:color="#color/purple" <-- note this value is different
android:state_pressed="true" />
<item
android:color="#color/blue"
android:state_checked="true" />
<item
android:color="#color/green"
android:state_disabled="true" />
<item
android:color="#color/orange" />
</selector>
but without all of the duplicate code. Also, if I want to change a color I can just change it in one place.
Is this possible?
I don't think you can do this on Android, You have to create multiple xml resources for different selector.
I try to apply my own design to edittext and to use android native selector when my edittext is enabled, focused, etc. The problem is that every time I touch the edittext and the native selector is working my edittext becomes smaller. Can anyone please suggest why this is happening?Here is my code snippet:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_window_focused="false" android:state_enabled="true"
android:drawable="#android:drawable/edit_text"/>
<item
android:state_window_focused="false" android:state_enabled="false"
android:drawable="#android:drawable/edit_text"/>
<item
android:state_pressed="true"
android:drawable="#android:drawable/edit_text"/>
<item
android:state_enabled="true" android:state_focused="true"
android:drawable="#android:drawable/edit_text"/>
<item
android:state_enabled="true"
android:drawable="#android:drawable/edit_text"/>
<item
android:state_focused="true"
android:drawable="#android:drawable/edit_text"/>
<item
android:drawable="#drawable/my_border" />
</selector>
And here I use my selector:
<EditText
android:layout_height="37dip"
android:layout_width="fill_parent"
android:layout_marginLeft="7dip"
android:layout_marginRight="7dip"
android:background="#layout/selector_input"
android:paddingLeft="5dip"
android:paddingRight="5dip"
android:inputType="textEmailAddress">
</EditText>
This is the code of my_border:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/white"/>
<stroke android:width="1dip" android:color="#color/border_green"/>
<corners android:radius="4dp" />
<padding android:left="1dip" android:top="1dip" android:right="1dip" android:bottom="1dip" />
</shape>
P.S. absolutely the same thing is happening with the buttons.
at first, thanks a lot for your post, helped me alot,
but your code above (sample for selector) wasnt working for me:
so i adapted it for others, so if someone searches howto mark a textfield as selected:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_window_focused="false" android:state_enabled="true"
android:drawable="#drawable/bottom_line_normal"/>
<item
android:state_window_focused="false" android:state_enabled="false"
android:drawable="#drawable/bottom_line_normal"/>
<item
android:state_pressed="true"
android:drawable="#drawable/bottom_line_focus"/>
<item
android:state_enabled="true" android:state_focused="true"
android:drawable="#drawable/bottom_line_focus"/>
<item
android:state_enabled="true"
android:drawable="#drawable/bottom_line_normal"/>
<item
android:state_focused="true"
android:drawable="#drawable/bottom_line_focus"/>
<item
android:drawable="#drawable/bottom_line_normal"/>
</selector>
have fun :=) good luck :)
Since no one was able to completely answer my question I will answer it by myself. The problem was that my edittext became smaller every time I touched it. That happens because native edittext background in Android has a transparent area around it. So I used a layer list to create my background also with a transparent area around it. Here is the code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:drawable="#drawable/transparent_background"
android:top="5dip"
android:right="5dip"
android:bottom="5dip"
android:left="5dip" />
<item
android:drawable="#drawable/my_border"
android:top="0dip"
android:right="0dip"
android:bottom="0dip"
android:left="0dip" />
</layer-list>
In my selector instead of my_border I use this xml.
That's it. Easy to do and hell difficult to find out how!
<item
android:drawable="#drawablemy_border" />
1. are you missing a slash [/]? And what is the definition of that drawable my_border
Ok, after I tried this files, the EditText doesn't use your selector when it's not enabled and appear with it's standard layout... so adding
<item
android:state_enabled="false"
android:drawable="#android:drawable/edit_text"/>
to your selector should be the solution