棒棒糖的backgroundTint对Button无效


82

我的活动中有一个按钮,我希望它具有主题的强调色。当然,我不必像制作必须棒棒糖之前那样制作自己的可绘制对象,而是自然要使用newbackgroundTint属性。

<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,但没有任何改变。

我还尝试在“活动”中以编程方式进行此操作,但没有任何改变。

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

为什么我的色彩被忽略?

编辑:只是为了澄清,我确实在棒棒糖设备上进行测试。其他窗口小部件(例如EditText)正确且自动着色。


3
此错误已在将来的版本中修复,但可接受的解决方案将在API 21+上运行。
alanv

Answers:


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

输出为-

在此处输入图片说明


将其标记为可接受的答案,因为几年后,我相信它是目前执行此操作的官方(也是最佳)方法。(次要细节:我可以肯定,在大多数情况下,您可以简单地使用Button代替AppCompatButton,它仍然可以使用)。
BoD

116

坏消息

就像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主题之一,否则compat视图将非常非常难过...;)

这适用于2.3.7(姜饼MR1)和5.0(棒棒糖“经典”)。


1
刚刚添加了更多信息-最重要的是,现在可以使用前一天发布的支持库的新版本(22.1)来实现按钮着色!
Snild Dolkow,2015年

8
您可以colorButtonNormal与AppCompat 22.1.1一起使用(仅为按钮设置主题),它在4.4.4和5.1上适用于我。
hunyadym 2015年

2
任何想法如何为TextView设置相同的东西?
Android开发人员

8
取而代之的是new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});您可以写得更简洁ColorStateList.valueOf(0xffffcc00);
Ashkan Sarlak,2015年

5
您可以在xml
上将

30

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

实际上,在查看平台的默认按钮drawable之后,我发现了执行此操作的“正确”方法:您必须在主题中定义它:

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

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

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

另外,您还可以通过定义以下内容来更改波纹颜色:

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

colorControlHighlight虽然会改变很多其他小部件。很高兴您已经解决了。
natario

5
您可以通过定义覆盖主题(例如,未定义父主题和仅定义一个属性)并使用android:theme属性将其应用于单个视图。
alanv

1
那么,如何解决API 22及更高版本呢?仅在API 21(包括关系5,星系S3)的某些设备还这个“错误” occours
吠陀

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使用一种支持方法。


@Marco使用:if (view instanceof TintableBackgroundView) { ((TintableBackgroundView) view).setSupportBackgroundTintList(tint); } else { ViewCompat.setBackgroundTintList(view, tint); }
Chessdork '16

这不适用于预棒棒糖设备上的ImageButton。
toobsco42

使用AppCompatButton.setSupportBackgroundTintList()时,我会收到警告,只能从同一库组(groupId = com.android.support)内调用AppCompatButton.setSupportBackgroundTintList
starkej2

它对我有用,但我必须逆转条件。
Rodrigo Venancio '18

“为什么只能从同一库组(groupId = com.android.support)中调用”为什么出现此警告?
Ferran Negre

22

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

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

您可以在此处检查不同的混合模式在此处查看漂亮的示例。


1
我已经使用了PorterDuff.Mode.SRC,并且运行良好
francisco_ssb

完美运作。就我而言,我想对API 17使用着色效果,这对我有所帮助。
ashishdhiman2007

2
这应该是公认的答案。确认正在使用
API20。– hardanger


9

我认为你需要有android:background设置,使android:backgroundTint工作。

为了更加准确,我猜想是您无法backgroundTint使用Material主题的默认按钮背景(定义为)RippleDrawable


1
我认为你是对的。实际上,我找到了执行所需操作的“正确”方法(请参阅我的答案)。
BoD

3

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

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

问题:FloatingActionButton.setBackgroundTintList(@Nullable ColorStateList着色)不再更改背景色

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

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

棒棒糖前置设备的材料设计

AppCompat(又名ActionBarCompat)最初是针对运行在Gingerbread上的设备的Android 4.0 ActionBar API的反向移植,它在反向移植的实现和框架实现之上提供了一个通用的API层。AppCompat v21提供了最新的API和功能集,适用于Android 5.0


Android支持库22.1

使用AppCompat时自动着色小部件的功能对于在整个应用程序中保持强大的品牌和一致性非常有用。扩大布局时,此操作会自动完成-用AppCompatButton替换Button,用AppCompatTextView替换TextView等,以确保每个都可以支持着色。在此版本中,那些支持色调的窗口小部件现已公开可用,即使您需要子类化一种受支持的窗口小部件,也可以使您保持色调支持。



2

如果我们查看支持库的源代码,就会发现它通常为已知按钮着色,但是如果我们更改按钮的形状(我有圆形按钮),则在api <= 21中无法正常工作。我们还可以看到TintManager成为公共类(appcompat-v7:23.1.1),因此我们可以从默认按钮形状(在5.0中为ok)中获取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);
        }

自从appcompat 23.2以来,他们更改了类(尽管它是公共的!)TintManager-> AppCompatDrawableManager,代码几乎保持不变
Pavel Biryukov

WTF ... getTintList已从公共更改为现在受保护;(需要使用反射:)
Pavel Biryukov

0

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


我意识到这一点,并且确实在棒棒糖设备上进行测试。我将更新问题以使其更清楚。
BoD 2015年

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'

现在,它又可以工作了。


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



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"/>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.