在 xml 中为按钮定义自定义形状。现在我想动态改变颜色。如何?

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

我有这个:

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>

我的按钮:

 <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" />

动态地,我想更改背景颜色(在 round_button xml 中定义)以编程方式.我有办法做到这一点吗?

您可以从代码构建形状,具体取决于您需要使用的颜色,从中创建一个 StateListDrawable 并将其设置为您的按钮背景。

我通过设置 ColorFilter 解决了这个问题:

Drawable mDrawable = context.getResources().getDrawable(R.drawable.balloons); 
mDrawable.setColorFilter(new PorterDuffColorFilter(0xffff00,PorterDuff.Mode.MULTIPLY));
myButton.setResource(mDrawable);

如果你想为你的按钮定义某些状态,你可以在xml中设置它们,而不必以编程方式进行(如果你这样做,你确实可以设置一个过滤器,但如果你有很多状态和条件 IMO,它可能会变得混乱。

我将在这里详细说明步骤:

1) 创建具有您想要的状态的 xml

您可以在具有已定义状态的可绘制文件夹中创建一个带有选择器的 xml。例如,

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>

我们称这个文件为button_bkg.xml。在上面的示例中,我列出了 3 种状态: 按下、禁用和默认 ,这意味着,当按下按钮时,它将呈现 bkg_is_pressed 背景,当我将按钮设置为禁用(在 xml 中或通过 setEnabled(boolean) 以编程方式设置,它将假定为 bkg_is_disabled 背景。

2) 创建背景

现在您将在您定义的 xml 文件中定义背景(bkg_is_pressed、bkg_is_default、bkg_is_pressed)。例如,在您的情况下,您将获取 round_button.xml 文件中定义的每个形状,并将它们分成您为状态定义的每个 xml 文件。在我的例子中,我定义了一个图层列表:

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>

您将为每个州执行此操作。

请务必注意,如果您要为 API 21+ 构建,您可以通过在 drawables-v21 文件夹中创建另一个 button_bkg.xml 文件来定义涟漪效果,该文件会是这样的:

button_bkg.xml(在您的 drawable-v21 文件夹中)

<?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" />

要使用波纹,您可以定义一种颜色,如下所述:

bkg_is_pressed.xml(在你的 drawable-v21 文件夹中)

<?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>

您只需将 button_bkg.xml 和 bkg_is_pressed.xml 放入您的 drawable-v21 文件夹文件中。在我的例子中,bkg_is_default 和 bkg_is_disabled.xml 对于 21+ 和 21- APIs 是相同的,所以我没有将它添加到我的 drawable-v21 文件夹中,我只是创建了它在可绘制文件夹中。

我想强调的是,您仍然需要常规可绘制文件夹中的其他文件,以便 API 21- 的设备能够正常工作。

3) 将该背景分配给您的按钮

最后,您只需为按钮定义背景:

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

所以,你有它。这样,您不需要以编程方式设置样式,您只需在 xml 文件中定义所有背景(根据您的状态)。 但是,如果您也更喜欢以编程方式设置它们,您可以这样做,只需使用 setBackground 并使用您定义的 xml 文件并应用您想要的状态逻辑(如果按下按钮, setBackground(bkg_is_pressed) 等等)

希望对您有所帮助,如果对您有用,请告诉我。