Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
372 views
in Technique[技术] by (71.8m points)

android - Defined custom shape for button in xml. Now I want to change the color dynamically. How?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

<?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/bkg_is_pressed" android:state_pressed="true"/>
        <item android:drawable="@drawable/bkg_is_disabled" android:state_enabled="false"/>
        <item android:drawable="@drawable/bkg_default"/>
</selector>

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

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
    <shape android:shape="rectangle">
            <corners android:radius="@dimen/button_corner_radius"/>
            <solid android:color="@color/color_alert"/>
            <stroke
                 android:width="@dimen/universal_1_pixel"
                    android:color="@color/color_gray_dark"/>
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <corners android:radius="@dimen/button_corner_radius"/>
            <solid android:color="@color/color_mask_highlighted"/>
        </shape>
    </item>
</layer-list>

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)

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/bkg_is_disabled" android:state_enabled="false" />
    <item android:drawable="@drawable/bkg_is_pressed" />

To use the ripple, you can define a color as explained below:

bkg_is_pressed.xml (in your drawable-v21 folder)

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/color_mask_highlighted">
    <item android:drawable="@drawable/bkg_is_default" />
</ripple>

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:

<Button
    ...
    android:background="@drawable/button_bkg
/>

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...