87

我的活动中有一个按钮,我希望它具有我的主题的强调色。与其像在棒棒糖之前那样制作我自己的可绘制对象,我自然更愿意使用新backgroundTint属性。

<Button
    android:id="@+id/btnAddCode"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/accent"
    android:text="@string/addressInfo_edit_addCode" />

不幸的是,它没有效果,按钮保持灰色。

我尝试了不同的值backgroundTintMode,但没有改变任何东西。

我还尝试在我的 Activity 中以编程方式进行操作,但这并没有改变任何东西。

addCodeView.findViewById(R.id.btnAddCode).setBackgroundTintList(
     getResources().getColorStateList(R.color.accent));

为什么我的色调被忽略了?

编辑:澄清一下,我确实在棒棒糖设备上进行测试。其他小部件(例如 EditText)已正确自动着色。

4

16 回答 16

118

坏消息

正如 BoD 所说,在 Lollipop 5.0(API 级别 21)中为 Button 的背景着色是没有意义的。

好消息

Lollipop 5.1(API 级别 22)似乎通过更改 btn_mtrl_default_shape.xml(以及其他文件)解决了这个问题:https ://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E!/#F0

好消息

新的支持库(22.1+ 版)为许多组件添加了向后兼容的着色支持,包括AppCompatButton

不幸的是,该android:backgroundTint属性仍然不起作用(也许我做错了什么)——所以你必须设置ColorStateListin 代码,使用setSupportBackgroundTintList(). 很高兴看到android:backgroundTint将来得到支持。更新:Marcio Granzotto 评论说app:backgroundTint适用于 AppCompatButton!请注意,它是app:,不是android:,因为它在应用程序/库中。

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <AppCompatButton
        android:id="@+id/mybutton"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Testing, testing"
        app:backgroundTint="#ff00ff"/>

</LinearLayout>

如果你让它继承AppCompatButton自.ButtonAppCompatActivity

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AppCompatButton v = (AppCompatButton) findViewById(R.id.mybutton);
        ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
        v.setSupportBackgroundTintList(csl);
    }
}

你当然应该ColorStateList从颜色资源中获取,但我很懒,所以......

哦,别忘了将您的应用主题建立在其中一个Theme.AppCompat主题上,否则兼容的视图会非常非常难过... ;)

这适用于 2.3.7(Gingerbread MR1)和 5.0(Lollipop 'Classic')。

于 2015-04-20T18:59:21.417 回答
30

似乎为可绘制的波纹着色是没有意义的(并且按钮的默认背景是可绘制的波纹)。

事实上,在查看了平台的默认按钮 drawable 之后,我发现了这样做的“正确”方法:您必须在主题中定义它:

    <item name="android:colorButtonNormal">@color/accent</item>

(当然这仅适用于 21 级以上。)

警告:由于这是在主题中定义的,因此它将为所有按钮使用给定的颜色(至少使用该主题的活动中的所有按钮。)

作为奖励,您还可以通过定义以下内容来更改波纹颜色:

    <item name="android:colorControlHighlight">@color/accent_ripple</item>
于 2015-01-02T12:41:52.210 回答
22

为了解决与 Android 5.0.x 上的着色相关的问题,我使用了这样的方法:

public static void setButtonTint(Button button, ColorStateList tint) {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP && button instanceof AppCompatButton) {
        ((AppCompatButton) button).setSupportBackgroundTintList(tint);
    } else {
        ViewCompat.setBackgroundTintList(button, tint);
    }
}

它仅对 API 21 使用支持方法,对所有其他情况使用 ViewCompat 方法。

于 2015-05-18T21:44:06.257 回答
22

我通常使用 PorterDuff 动态地执行此操作:

mbutton = (Button) findViewById(R.id.mybutton);
mbutton.getBackground().setColorFilter(anycolor, PorterDuff.Mode.MULTIPLY);

您可以在此处查看不同的混合模式,并此处查看不错的示例。

于 2015-08-25T10:42:35.363 回答
20

只需使用app:backgroundTint代替android:backgroundTint,色调将在棒棒糖下方生效。原因是AppCompatActivity用于AppCompatViewInflater将Button或TextView自动更改为AppCompatButton或AppCompatTextView,然后app:backgroundTint生效。

在此处输入图像描述

在我的项目中,我使用了它,它起作用了。

于 2016-07-13T15:08:30.133 回答
18

在 API 19 到 API 27 上测试

<?xml version="1.0" encoding="utf-8"?>
  <android.support.v7.widget.AppCompatButton 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/retry"
    android:textColor="@android:color/white"
    app:backgroundTint="@android:color/holo_red_dark" />

产生输出为 -

在此处输入图像描述

于 2018-04-04T16:52:01.827 回答
9

我认为你需要准备android:backgroundandroid:backgroundTint工作。

更准确地说,我的猜测是你不能backgroundTint使用 Material 主题的默认按钮背景,它被定义为RippleDrawable.

于 2015-01-02T00:52:58.970 回答
4

只需使用 app:backgroundTint 而不是 android:backgroundTint

于 2018-01-27T07:07:00.117 回答
3

谷歌报告了类似的问题https://code.google.com/p/android/issues/detail?id=201873

但在 Android 支持库发布后,修订版23.2.1 (2016 年 3 月)此错误已解决。

问题:FloatingActionButton.setBackgroundTintList(@Nullable ColorStateList tint) 不再改变背景颜色

将支持库更新为Android Support Library to 23.2.1

使用设计支持库(23.2.1)appcompatwidgets 如下

Pre-Lollipop 设备的材料设计

AppCompat(又名 ActionBarCompat)最初是为运行在 Gingerbread 上的设备提供的 Android 4.0 ActionBar API 的向后移植,在向后移植的实现和框架实现之上提供了一个通用 API 层。AppCompat v21 提供了与 Android 5.0 保持同步的 API 和功能集


Android 支持库 22.1

使用 AppCompat 时自动着色小部件的能力对于在整个应用程序中保持强大的品牌和一致性非常有帮助。这是在扩展布局时自动完成的 - 用 AppCompatButton 替换 Button,用 AppCompatTextView 替换 TextView 等,以确保每个都可以支持着色。在此版本中,这些着色感知小部件现已公开提供,即使您需要对受支持的小部件之一进行子类化,您也可以继续支持着色。

于 2016-03-08T12:53:39.150 回答
2

如果我们查看支持库的源代码,我们会看到它正常着色它是已知的按钮,但是如果我们改变按钮的形状(我有圆形按钮),在 api<=21 中着色不起作用。我们还可以看到 TintManager 成为公共类(appcompat-v7:23.1.1),因此我们可以从默认按钮形状(在 5.0 中可以着色)中为当前主题获取 ColorStateList(因此我们不必创建数组颜色):

    Context c = ...; // activity
    AppCompatButton ab = ...; // your button
    // works ok in 22+:
    if (Build.VERSION.SDK_INT <= 21) {
        // default appcompat button, that is tinted ok with current theme colors "abc_btn_default_mtrl_shape":
        // ColorStateList tint = TintManager.get(c).getTintList(R.drawable.abc_btn_default_mtrl_shape);
        // Appcompat 23.2 change:
        ColorStateList tint = AppCompatDrawableManager.get().getTintList(c, R.drawable.abc_btn_default_mtrl_shape);
        ab.setSupportBackgroundTintList(tint);
        }
于 2015-11-30T08:17:03.657 回答
0

因为属性backgroundTint仅在 API 级别 21 及更高级别中使用

于 2015-01-02T00:17:34.763 回答
0

我不确定这是否被推荐,但你可以试试这个:

Drawable newDrawable = mBtnAction.getBackground();  // obtain Bg drawable from the button as a new drawable
DrawableCompat.setTint(newDrawable, mActivity.getHomeTobBarBGColor());  //set it's tint
mBtnAction.setBackground(newDrawable);  //apply back to button

在一般意义上它是有效的。试过了ViewCompat,但似乎不能正常工作。

于 2017-09-08T06:44:30.193 回答
0

你可以backgroundTint <android.support.design.button.MaterialButton使用"com.android.support:design:28.0.0-rc01"版本

于 2018-08-13T07:31:22.203 回答
0

请注意 recyclerview 最新更新的库也可能导致此错误。

这个命令

  sendBtnView.setBackgroundTintList(colorState)

过去工作得很好,但停止为我工作。经过研究发现原因是添加到 gradle 依赖项的库:

  compile 'com.android.support:recyclerview-v7:+'

因此,我尝试将其更改为 23.02.1,正如 Amit Vaghela 帖子中所推荐的那样。我改为

  compile  'com.android.support:recyclerview-v7:23.02.1'

但是gradle错误说recyclerview lib没有这个版本(23.02.1)(gradle在Jcenter raw.github或repo中找不到它)。

然后,因为我知道 setBackgroundTintList 命令过去在我在 gradle 依赖项中拥有的所有其他库中的版本 22.02.0' 中运行良好。所以我将其更改为:

compile   'com.android.support:recyclerview-v7:22.02.0'

现在它又可以工作了。

于 2016-03-30T11:08:29.937 回答
0

如果您正在开发目标sdk高于 api 21 的应用程序,而您minSdkVersion is 21(Lollipop)

android:backgroundTint="@color/accent"

你可以简单地说..

android:background="@color/accent"
于 2021-12-15T10:36:05.057 回答
0

如果您使用的是 androidx,则在 android 5.1 上添加前缀和非前缀版本解决了问题:

<style name="Button_Primary">
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:backgroundTint">@color/button_primary_selector</item>
    <item name="backgroundTint">@color/button_primary_selector</item><!--needed for android 5-->
</style>

button_primary 选择器位于color具有以下内容的文件夹中:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:local="http://schemas.android.com/apk/res-auto">
    <item android:state_enabled="true" android:color="@android:color/holo_blue_dark" />
    <item android:state_enabled="false" android:color="@android:color/darker_gray" />
</selector>

并将其应用于常规按钮AppCompatActivity

<Button style="@style/Button_Primary"/>
于 2020-09-09T15:29:06.590 回答