Friday, 10 June 2016

XML : Change Button custom shape states color programatically

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.

No comments:

Post a Comment