I have this:
round_button.xml
<xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#dec60000"/>
<size android:width="150dp" android:height="150dp"/>
</shape>
</item>
<item android:state_pressed="false">
<shape android:shape="oval">
<solid android:color="#860000"/>
<size android:width="150dp" android:height="150dp"/>
</shape>
</item>
My Button:
<Button
android:id="@+id/incrementBTN"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/round_button"
android:onClick="onClick"
android:soundEffectsEnabled="true"
android:text="0"
android:textSize="50sp"
tools:ignore="HardcodedText" />
Dynamically, I want to change the background color (which is defined in the round_button xml) programmatically. Is there a way I can do this?
I solved it by setting a ColorFilter:
If you want to define certain states for your button, you could set them all in xml, without having to do it programmatically (if you do, you can indeed set a filter, but it can get messy if you have many states and conditions IMO).
I'll detail the steps here:
1) Creating a xml with the states you want
You can create a xml with a selector in your drawable folder with the defined states. As an example,
button_bkg.xml
Let's call this file button_bkg.xml. In the example above, I have listed 3 states: pressed, disabled and default, which means that, when the button is pressed, it will assume the bkg_is_pressed background and, when I set the button to disabled (either in xml or programmatically through setEnabled(boolean), it will assume bkg_is_disabled background.
2) Creating the backgrounds
Now you will define what you want the background to be in the xml files you defined (bkg_is_pressed, bkg_is_default, bkg_is_pressed). In your case, in example, you would take each shape defined in your round_button.xml file and separate them into each one of the xml files you defined for the states. In my case, I defined a layer-list:
bkg_is_pressed.xml
You will do that for each of the states.
It is important to note that, if you are going to build for API 21+, you can define a ripple effect by creating ANOTHER button_bkg.xml file in your drawables-v21 folder, which would be like this:
button_bkg.xml (in your drawable-v21 folder)
To use the ripple, you can define a color as explained below:
bkg_is_pressed.xml (in your drawable-v21 folder)
You only have to put the button_bkg.xml and the bkg_is_pressed.xml into your drawable-v21 folder file. In my case, bkg_is_default and bkg_is_disabled.xml were the same for both 21+ and 21- APIs, so I didn't add it to my drawable-v21 folder, I just created it in the drawable folder.
I want to emphasize that you STILL need the other files in your regular drawable folder so that devices with API 21- will work properly.
3) Assigning that background to your button
Lastly, you just have to define that background to your button:
So, there you have it. This way, you don't need to set the styles programmatically, you can just define all the backgrounds (according to your states) in the xml files. But, if you also prefer to set them all programmatically, you can do the same, just use setBackground and use the xml files you defined and apply the state logic you want to it (if button is pressed, setBackground(bkg_is_pressed) and so on)
I hope that helps, let me know if that works for you.
You could construct the shapes from code, depending on the color you need to use, create a StateListDrawable from those and set it as your buttons background.