在今天AppCompat更新出来之前,我可以改变Android L中按钮的颜色,但在旧版本上不行。在包含新的AppCompat更新后,我无法更改两个版本的颜色,当我尝试时,按钮就消失了。有人知道怎么改变按钮的颜色吗?

下面的图片展示了我想要达到的目标:

白色按钮是默认的,红色按钮是我想要的。

这是我之前在styles.xml中改变按钮颜色所做的:

<item name="android:colorButtonNormal">insert color here</item>

要动态地进行:

button.getBackground().setColorFilter(getResources().getColor(insert color here), PorterDuff.Mode.MULTIPLY);

我也改变了@android:style/ theme . material . light的主题父元素。到Theme.AppCompat.Light.DarkActionBar


当前回答

一种方法是让你只指向一个样式而不是主题,你的应用程序中的所有按钮都是一样的。 在themes.xml中添加一个主题

    <style name="Theme.MyApp.Button.Primary.Blue" parent="Widget.AppCompat.Button">
        <item name="colorButtonNormal">@color/someColor</item>
        <item name="android:textColorPrimary">@android:color/white</item>
    </style>

现在在styles.xml中添加

    <style name="MyApp.Button.Primary.Blue" parent="">
        <item name="android:theme">@style/Theme.MyApp.Button.Primary.Blue</item>
    </style>

现在在你的布局中,简单地指向按钮的样式

    <Button
        ...
        style="@style/MyApp.Button.Primary.Blue"
        ...  />

其他回答

编辑(22.06.2016):

Appcompat库开始支持材料按钮后,我张贴了原始的回应。在这篇文章中,你可以看到凸起和扁平按钮的最简单实现。

最初的回答:

因为AppCompat还不支持按钮,你可以使用xml作为背景。为了做到这一点,我查看了Android的源代码,并找到了样式化材质按钮的相关文件。

1 -从源头看材料按钮的原始实现。

看看android上的btn_default_material.xml源代码。

您可以将该文件复制到项目drawable-v21文件夹中。但是不要碰这里的颜色。您需要更改的文件是第二个文件。

drawable-v21 / custom_btn.xml

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
    <item android:drawable="@drawable/btn_default_mtrl_shape" />
</ripple>

2 -获得原始材料按钮的形状

正如你意识到的那样,在这个可绘制的图形中使用了一个形状,你可以在这个源代码文件中找到它。

<inset xmlns:android="http://schemas.android.com/apk/res/android"
   android:insetLeft="@dimen/button_inset_horizontal_material"
   android:insetTop="@dimen/button_inset_vertical_material"
   android:insetRight="@dimen/button_inset_horizontal_material"
   android:insetBottom="@dimen/button_inset_vertical_material">
<shape android:shape="rectangle">
    <corners android:radius="@dimen/control_corner_material" />
    <solid android:color="?attr/colorButtonNormal" />
    <padding android:left="@dimen/button_padding_horizontal_material"
             android:top="@dimen/button_padding_vertical_material"
             android:right="@dimen/button_padding_horizontal_material"
             android:bottom="@dimen/button_padding_vertical_material" />
</shape>

3 -获取材料按钮的尺寸

在这个文件中你可以找到文件中用到的一些维度。您可以复制整个文件并将其放入values文件夹中。这对于将相同的尺寸(用于材质按钮)应用到所有按钮是很重要的

4 -为旧版本创建另一个可绘制文件

对于旧版本,您应该有另一个具有相同名称的可绘制对象。我直接把项目内联而不是引用。你可能想要引用它们。但同样,最重要的是材质按钮的原始尺寸。

可拉的/ custom_btn.xml

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- pressed state -->
    <item android:state_pressed="true">
        <inset xmlns:android="http://schemas.android.com/apk/res/android"
            android:insetLeft="@dimen/button_inset_horizontal_material"
            android:insetTop="@dimen/button_inset_vertical_material"
            android:insetRight="@dimen/button_inset_horizontal_material"
            android:insetBottom="@dimen/button_inset_vertical_material">
            <shape android:shape="rectangle">
                <corners android:radius="@dimen/control_corner_material" />
                <solid android:color="@color/PRESSED_STATE_COLOR" />
                <padding android:left="@dimen/button_padding_horizontal_material"
                    android:top="@dimen/button_padding_vertical_material"
                    android:right="@dimen/button_padding_horizontal_material"
                    android:bottom="@dimen/button_padding_vertical_material" />
            </shape>
        </inset>
    </item>
    
    <!-- focused state -->
    <item android:state_focused="true">
        <inset xmlns:android="http://schemas.android.com/apk/res/android"
            android:insetLeft="@dimen/button_inset_horizontal_material"
            android:insetTop="@dimen/button_inset_vertical_material"
            android:insetRight="@dimen/button_inset_horizontal_material"
            android:insetBottom="@dimen/button_inset_vertical_material">
            <shape android:shape="rectangle">
                <corners android:radius="@dimen/control_corner_material" />
                <solid android:color="@color/FOCUSED_STATE_COLOR" />
                <padding android:left="@dimen/button_padding_horizontal_material"
                    android:top="@dimen/button_padding_vertical_material"
                    android:right="@dimen/button_padding_horizontal_material"
                    android:bottom="@dimen/button_padding_vertical_material" />
            </shape>
        </inset>
    </item>
    
    <!-- normal state -->
    <item>
        <inset xmlns:android="http://schemas.android.com/apk/res/android"
            android:insetLeft="@dimen/button_inset_horizontal_material"
            android:insetTop="@dimen/button_inset_vertical_material"
            android:insetRight="@dimen/button_inset_horizontal_material"
            android:insetBottom="@dimen/button_inset_vertical_material">
            <shape android:shape="rectangle">
                <corners android:radius="@dimen/control_corner_material" />
                <solid android:color="@color/NORMAL_STATE_COLOR" />
                <padding android:left="@dimen/button_padding_horizontal_material"
                    android:top="@dimen/button_padding_vertical_material"
                    android:right="@dimen/button_padding_horizontal_material"
                    android:bottom="@dimen/button_padding_vertical_material" />
            </shape>
        </inset>
    </item>
</selector>

结果

你的按钮会在棒棒糖设备上产生连锁反应。旧版本将有完全相同的按钮,除了涟漪效应。但是因为你为不同的状态提供了可绘制对象,它们也会响应触摸事件(就像旧的方式一样)。

这个SO的回答帮助我得到了一个答案https://stackoverflow.com/a/30277424/3075340

我使用这个实用工具方法来设置按钮的背景色调。它适用于棒棒糖之前的设备:

// Set button background tint programmatically so it is compatible with pre-lollipop devices.
public static void setButtonBackgroundTintAppCompat(Button button, ColorStateList colorStateList){
    Drawable d = button.getBackground();
    if (button instanceof AppCompatButton) {
        // appcompat button replaces tint of its drawable background
        ((AppCompatButton)button).setSupportBackgroundTintList(colorStateList);
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        // Lollipop button replaces tint of its drawable background
        // however it is not equal to d.setTintList(c)
        button.setBackgroundTintList(colorStateList);
    } else {
        // this should only happen if
        // * manually creating a Button instead of AppCompatButton
        // * LayoutInflater did not translate a Button to AppCompatButton
        d = DrawableCompat.wrap(d);
        DrawableCompat.setTintList(d, colorStateList);
        button.setBackgroundDrawable(d);
    }

}

如何在代码中使用:

Utility.setButtonBackgroundTintAppCompat(myButton,
ContextCompat.getColorStateList(mContext, R.color.your_custom_color));

这样,如果你只是想改变背景色调,只是想保持漂亮的按钮效果,你就不必指定ColorStateList。

这是我在android + 4.0中的appcompat-v7 . 22.2.0工作

在你的styles.xml中

<style name="Button.Tinted" parent="Widget.AppCompat.Button">
    <item name="colorButtonNormal">YOUR_TINT_COLOR</item>
    <item name="colorControlHighlight">@color/colorAccent</item>
    <item name="android:textColor">@android:color/white</item>
</style>

在布局文件中

<Button
    android:id="@+id/but_next"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/but_continue"
    android:theme="@style/Button.Tinted" />

如果你想用任何颜色的代码来做这个:

DrawableCompat.setTintList(button.getBackground(), ColorStateList.valueOf(yourColor));

如果你只想要“平面”材质按钮,你可以使用selectableItemBackground属性自定义他们的背景,如下所述。