Lollipop 的 backgroundTint 对 Button 没有影响

Lollipop's backgroundTint has no effect on a Button

我的活动中有一个按钮,我希望它具有我的主题的强调色。 我不想像 Lollipop 之前那样自己制作可绘制对象,自然而然地我想使用新的 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));

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

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

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

中使用

我认为您需要设置 android:background 才能使 android:backgroundTint 正常工作。

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

似乎给波纹绘图着色是没有意义的(按钮的默认背景是波纹绘图)。

事实上,在查看平台的默认按钮 drawable 之后,我发现 "correct" 方法可以做到这一点:。你必须在你的主题中定义它:

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

(当然这只适用于21+级。)

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

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

    <item name="android:colorControlHighlight">@color/accent_ripple</item>

坏消息

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

好消息

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

好消息

新的支持库(版本 22.1+)adds backward-compatible tinting support to lots of components, including AppCompatButton!

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

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

如果您让它继承自 AppCompatActivity,您的 activity 将自动膨胀 AppCompatButton 而不是正常的 Button

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')。

要解决与 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 方法。

我通常使用 PorterDuff 动态地完成它:

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

您可以检查不同的混合模式here and nice examples here

如果我们查看支持库的源代码,我们会发现它通常为已知按钮着色,但如果我们更改按钮的形状(我有圆形按钮),着色在 api<=21。 我们还可以看到 TintManager 变成了 public class (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);
        }

在 google 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如下

Material Design for Pre-Lollipop Devices :

AppCompat (aka ActionBarCompat) started out as a backport of the Android 4.0 ActionBar API for devices running on Gingerbread, providing a common API layer on top of the backported implementation and the framework implementation. AppCompat v21 delivers an API and feature-set that is up-to-date with Android 5.0


Android Support Library 22.1 :

The ability to tint widgets automatically when using AppCompat is incredibly helpful in keeping strong branding and consistency throughout your app. This is done automatically when inflating layouts - replacing Button with AppCompatButton, TextView with AppCompatTextView, etc. to ensure that each could support tinting. In this release, those tint aware widgets are now publicly available, allowing you to keep tinting support even if you need to subclass one of the supported widgets.

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

这个命令

  sendBtnView.setBackgroundTintList(colorState)

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

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

所以我尝试将其更改为 23.02.1,正如 Amit Vaghela post 中推荐的那样。 我改成了

  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'

现在又可以用了。

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

In my project I used it, it worked.

我不确定是否推荐这样做,但您可以试试这个:

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,但似乎无法正常工作。

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

测试于 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" />

产生输出为 -

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

如果您使用的是 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"/>

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

android:backgroundTint="@color/accent"

你可以简单地说..

android:background="@color/accent"