Change Button custom shape states color programmatically - java

There are a lot of answers on this site regarding changing button colors, but none that I have managed to use in my case.
I want to be able to dynamically change a button's color, that button still needs to have a visual feedback on press, and it needs rounded corners.
The rounded corners part was decided upon recently, so previously I used something like this:
StateListDrawable states = new StateListDrawable();
states.addState(new int[]{android.R.attr.state_pressed},
new ColorDrawable(hsvDarkenColor(theme.get_buttonsBgColor())));
states.addState(new int[]{android.R.attr.state_focused},
new ColorDrawable(hsvDarkenColor(theme.get_buttonsBgColor())));
states.addState(new int[]{},
new ColorDrawable(Color.parseColor(theme.get_buttonsBgColor())));
((Button) button).setBackgroundDrawable(states);
//this is for the focused/pressed state of the button
private static int hsvDarkenColor(String originalColor)
{
float[] hsv = new float[3];
int color = Color.parseColor(originalColor);
Color.colorToHSV(color, hsv);
hsv[2] *= 0.8f; // value component
return Color.HSVToColor(hsv);
}
However this doesn't preserve the rounded corners shape of the buttons, it makes them into squares.
My default buttons' backgrounds are a list of states each with it's own drawable, for pressed and unpressed, etc.
In styles.xml:
<style name="xx.Light.ScanButton" parent="android:style/Widget.Button">
<item name="android:focusable">true</item>
<item name="android:background">#drawable/xx_scan_button</item>
<item name="android:textStyle">normal</item>
<item name="android:textColor">#color/text_light</item>
</style>
In drawable/xx_scan_button.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Non focused states -->
<item
android:state_focused="false"
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/xx_scan_button_normal"
/>
<item
android:state_focused="false"
android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/xx_scan_button_pressed"
/>
<!-- Focused states -->
<item
android:state_focused="true"
android:state_selected="false"
android:state_pressed="false"
android:drawable="#drawable/xx_scan_button_pressed"
/>
<item
android:state_focused="true"
android:state_selected="true"
android:state_pressed="false"
android:drawable="#drawable/xx_scan_button_pressed"
/>
<!-- Pressed -->
<item
android:state_pressed="true"
android:drawable="#drawable/xx_scan_button_pressed"
/>
<!-- Disabled -->
<item
android:state_enabled="false"
android:drawable="#drawable/xx_scan_button_normal"
/>
</selector>
And in drawable/xx_scan_button_normal.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:bottomRightRadius="5dp"
android:bottomLeftRadius="0dp"
android:topLeftRadius="0dp"
android:topRightRadius="5dp"/>
<solid
android:color="#C74700"
/>
<padding
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
/>
<size
android:width="270dp"
android:height="60dp"
/>
</shape>
TL;DR: I need some way to extract the shape drawable from a drawable state list from a button in order to change it's color.
Or if you guys have a better solution, I'm all ears.

You will have to make separate drawables for individual color and change drawable programmatically not color. Changing color from program overrides the drawble.

Related

my application ignores any changes in background color of buttons

i'm trying to customize my alert dialog. but i can not change the background color of buttons.
i tried drawable button designing, style, setting direct color in xml and also setting color by java codes in the activity but i could not change it.
the shape of the button changes but the color only can be either the default color or transparent color.
the xml coding of button itself:
<Button
android:id="#+id/btnDenied"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="35dp"
android:layout_marginBottom="15dp"
android:background="#drawable/button_selected" //// or #drawable/button_costume
android:text="#string/button_no" />
the selector:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed = "true">
<shape>
<solid android:color="#FFEB3B"/>
</shape>
</item>
<item android:state_pressed = "false">
<shape>
<solid android:color="#FFC107"/>
</shape>
</item>
</selector>
and another drawable file:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners
android:radius="50dp"/>
<solid
android:color="#color/colorHeader"/>
</shape>
and i also tried this style:
<style name="Button_Style"
parent="#android:style/Widget.Button">
<item name="android:textSize">14sp</item>
<item name="android:background">#color/colorHeader</item>
<item name="android:textColor">#1B1B22</item>
<item name="android:textStyle">bold</item>
<item name="android:layout_margin">2dp</item>
</style>
but non of them could change the color of the button.
The code that I have written is 100 percent correct, but sometimes Android Studio does some wrong tasks, so solve these issues either by running the program again, or doing the following steps:
Clean Project , From the build menu .
Rebuild Project .
And I got this problem with me not to show errors in xml file,
I hope this thing helped you.

Dynamic radio button doesn't wrap_content

I have created a radio button with a custom drawable like this.
I used my custom selector
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/est_status_radio_checked" android:state_checked="true" android:state_enabled="true" />
<item android:drawable="#drawable/est_status_radio_checked" android:state_checked="true" android:state_enabled="false" />
<item android:drawable="#drawable/est_status_radio_unchecked" android:state_checked="false" /></selector>
with the radio button like the following
<style name="AppTheme.StatusRadioButtons">
<item name="fontPath">fonts/SFUIText-Semibold.ttf</item>
<item name="android:textSize">10sp</item>
<item name="android:background">#drawable/establishment_status_selector</item>
<item name="android:elevation">5dp</item>
<item name="android:paddingLeft">5dp</item>
<item name="android:textColor">#drawable/est_status_text_color</item>
<item name="android:button">#null</item>
</style>
<RadioButton
style="#style/AppTheme.StatusRadioButtons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:checked="false"
android:gravity="center"
android:text="Stopped" />
Everything works fine , but now the requirement is to create dynamic buttons.
For some reason when i create a dynamic radio button , the drawable appears stretched :#
I have created the button like this
private RadioButton createRadioForStatus(EstablishmentStatus establishmentStatus) {
RadioButton radioButton = new RadioButton(getContext());
radioButton.setCompoundDrawablePadding(0);
radioButton.setPadding(0,0,0,0);
radioButton.setBackground(ContextCompat.getDrawable(getContext(),R.drawable.establishment_status_selector));
radioButton.setButtonDrawable(null);
radioButton.setTextSize(10);
radioButton.setElevation(getResources().getDimension(R.dimen.unit_small));
radioButton.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));// wrap content buttons are working perfectly in xml but for some motherfucking reason are not wrapping the content properly when done programatically
radioButton.setText(establishmentStatus.getName());
return radioButton;
}
My selector drawable is like this
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/colorPrimary" />
<corners android:radius="30dp" />
</shape>
</item>
<item
android:bottom="5dp"
android:left="5dp"
android:right="55dp"
android:top="5dp">
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#color/colorWhite" />
<size
android:width="10dp"
android:height="10dp"></size>
</shape>
</item>
You should set your src of radio-button in separate directory and then find it by R
Your RadioButton should be inside the same RadioGroup, Something like this:
RadioGroup radioGroup = new RadioGroup(this);
RadioButton radioButton1= new RadioButton(this);
RadioButton radioButton2= new RadioButton(this);
radioGroup.addView(radioButton1);
radioGroup.addView(radioButton2);
I hope this will help.

Custom button drawable state_pressed and state_checked not working on CheckBox or RadioButton - Android

I am setting custom drawable to the checkbox button,
But only android:state_checked="true" and android:state_checked="false" seem to work.
Other states aren't working.
I am unable to set a custom drawable on pressed state.
This is the selector I am using:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:drawable="#drawable/radio_btn_selected" />
<item android:state_checked="false" android:drawable="#drawable/radio_btn_normal" />
<item android:state_pressed="true" android:drawable="#drawable/radio_btn_pressed" />
<item android:state_focused="true" android:drawable="#drawable/radio_btn_pressed" />
<item android:drawable="#drawable/radio_btn_normal"/> <!-- default -->
</selector>
This is how I am setting it to radio button:
radioButton.setButtonDrawable(R.drawable.radio_btn_selectors);
android:state_pressed="true" and android:state_focused="true" are not working because of the ordering in which you declared various states. Whenever you declare a drawable like this, system will goes from top to bottom and if a state is matched, it doesn't look for the other ones and applies the changes based on the very first selection. I think here android:state_checked="false" condition might be executing instead of android:state_pressed="true" and android:state_focused="true". So move android:state_checked="false" to the bottom and then try.

How to change button background colour without changing onclick/onpress colors

I'm wondering if this is even possible but hopefully someone will be able to confirm.
I've created a simple custom button layout in XML to handle the focused/pressed and dormant states. See code at bottom. This works fine when I use it to create a new button. However, I would like the user to be able to change the button colour via a colour picker if they don't like the default. However, the only way I know to change the button background colour programmatically is to use
mybutton.setBackgroundColor(someothercolor);
but if I do this it overwrites all the XML layout code and I lose the colour change when the button is pressed. I guess this is by design as I'm essentially overwriting the entire background style but what I really want to do is to allow the user to change the button colour when its not pressed to something custom but keep the style and layout of the other states the button could be in (i.e. what happens when its pressed).
Any ideas anyone?
Thank you in advance.
Nat
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="#color/originalbuttoncolor" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:drawable="#color/originalbuttoncolor" />
</selector>
Maybe you can consider creating a ColorStateList programmatically, as described here: How do I create ColorStateList programmatically?
You can try this:
1. remove the default color <item android:drawable="#color/originalbuttoncolor" />
2.Then:
`StateListDrawable ret = (StateListDrawable) res.getDrawable(R.drawable.btn_selector);
ret.addState(new int[] {}, new ColorDrawable(your_desire_color));
mybutton.setBackgroundDrawable(ret);`
You can make multiple files of your selector-list, each one contain different color as the default color, and link those files to the color picker, so you save your logic of selector.
For example:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="#color/originalbuttoncolor" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:drawable="#color/originalbuttoncolor" />
</selector>
And:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="#color/yellowbuttoncolor" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#color/someotherbuttoncolor" />
<item android:drawable="#color/originalbuttoncolor" />
</selector>
Edit: if you want to take color from user, this may work, if the selector state will overrided by this code:
ColorDrawable cd = new ColorDrawable(); // initialize it from the color picker;
StateListDrawable states = (StateListDrawable) mybutton.getBackground();
states.addState(new int[] {-android.R.attr.state_pressed, android.R.attr.state_focused}, cd); // the minus means false value
mybutton.setBackground(states);

State list drawable for textview

I just want to put a text, for example in blue, and when i press it to turn in another color.
But not like setTextColor(int) but more like a link, that's why i why thinking about state list drawable. Do you know how can i implement this ?
You can use colors instead of drawables for that.
Use some thing like this:
file: res/color/state_white_blue.xml
<?xml version="1.0" encoding="utf-8"?>
<selector
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_focused="true"
android:state_pressed="true"
android:color="#color/text_white" />
<item
android:state_focused="false"
android:state_pressed="true"
android:color="#color/text_white" />
<item
android:state_focused="true"
android:color="#color/text_white" />
<item
android:state_selected="true"
android:color="#color/text_white" />
<item
android:state_checked="true"
android:color="#color/text_white" />
<item
android:state_selected="false"
android:state_checked="false"
android:state_focused="false"
android:state_pressed="false"
android:color="#color/text_blue" />
</selector>

Categories