【问题标题】:Lollipop's backgroundTint has no effect on a ButtonLollipop 的 backgroundTint 对 Button 没有影响
【发布时间】:2015-02-28 09:57:27
【问题描述】:

我的 Activity 中有一个按钮,我希望它具有我的主题的强调色。 与其像在棒棒糖之前那样制作自己的可绘制对象,我自然更愿意使用新的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)已正确自动着色。

【问题讨论】:

  • 这是一个已在未来版本中修复的错误,但可接受的解决方案将适用于 API 21+。

标签: android android-layout tint


【解决方案1】:

坏消息

正如 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+)adds backward-compatible tinting support 对许多组件,包括 AppCompatButton

不幸的是,android:backgroundTint 属性仍然不起作用(也许我做错了什么)——所以你必须在代码中设置ColorStateList,使用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>

如果你让它继承自AppCompatActivity,你的活动将自动膨胀一个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 主题之一上,否则compat 视图会非常非常难过... ;)

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

【讨论】:

  • 刚刚添加了更多信息 -- 最重要的是,现在可以使用前几天发布的支持库的新版本 (22.1) 实现按钮着色!
  • 您可以将colorButtonNormal 与 AppCompat 22.1.1 一起使用(仅为按钮设置主题),它适用于 4.4.4 和 5.1。
  • 知道如何为 TextView 设置相同的东西吗?
  • 你可以写更简洁的ColorStateList.valueOf(0xffffcc00);,而不是new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
  • 您可以在 xml 上使用 android.support.v7.widget.AppCompatButton 和 app:backgroundTint
【解决方案2】:

似乎给ripple drawable着色是没有意义的(按钮的默认背景是ripple drawable)。

事实上,在查看了平台的默认按钮drawable之后,我找到了“正确”的方法:你必须在你的主题中定义它:

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

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

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

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

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

【讨论】:

  • colorControlHighlight 会改变很多其他小部件。很高兴你解决了。
  • 您可以通过定义一个覆盖主题(例如,没有父主题,只定义一个属性)并使用 android:theme 属性将其应用于单个视图。
  • 那么它是如何为 API 22 及更高版本修复的?此外,此“错误”仅出现在 API 21 的某些设备中(包括 nexus 5、galaxy s3)
【解决方案3】:

为了解决与 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); }
  • 这不适用于预棒棒糖设备上的 ImageButton。
  • 我在使用 AppCompatButton.setSupportBackgroundTintList() 时收到 lint 警告 AppCompatButton.setSupportBackgroundTintList 只能从同一个库组中调用 (groupId=com.android.support)
  • 它对我有用,但我不得不颠倒条件。
  • "只能从同一个库组中调用 (groupId=com.android.support" 为什么会出现这个警告?
【解决方案4】:

我通常使用 PorterDuff 动态地进行:

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

您可以查看不同的混合模式here 和很好的示例here

【讨论】:

  • 我用过 PorterDuff.Mode.SRC,效果很好
  • 完美运行。就我而言,我想在 API 17 上使用着色效果,这对我有帮助。
  • 这应该是公认的答案。确认使用 API 20。
【解决方案5】:

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

In my project I used it, it worked.

【讨论】:

    【解决方案6】:

    在 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 并且它仍然可以工作)。
    【解决方案7】:

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

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

    【讨论】:

    • 我认为你是对的。事实上,我找到了做我想做的事情的“正确”方式(见我的回答)。
    【解决方案8】:

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

    【讨论】:

    • 这立即奏效了。我仍然不明白为什么它似乎适用于所有 API 版本。
    【解决方案9】:

    googlehttps://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

    使用 design support library(23.2.1)appcompatwidgets 如下

    Material Design for Pre-Lollipop Devices

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


    Android Support Library 22.1

    使用 AppCompat 时自动为小部件着色的功能是 非常有助于保持强大的品牌和一致性 整个应用程序。这是在膨胀布局时自动完成的 - 将 Button 替换为 AppCompatButton,TextView 替换为 AppCompatTextView 等,以确保每个都可以支持着色。在 在这个版本中,这些色彩感知小部件现已公开发布, 即使您需要子类化一个,也允许您继续着色支持 支持的小部件。

    【讨论】:

      【解决方案10】:

      如果我们查看支持库的源代码,我们会看到它正常着色它是已知的按钮,但是如果我们改变按钮的形状(我有圆形按钮)着色在 api 中无法正常工作

          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 代码几乎保持不变
      • WTF... getTintList 现在从公共更改为受保护;(需要使用反射:)
      【解决方案11】:

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

      【讨论】:

      • 我意识到这一点,而且我确实在 Lollipop 设备上进行测试。我将更新问题以明确这一点。
      【解决方案12】:

      请注意,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'
      

      现在它又可以工作了。

      【讨论】:

        【解决方案13】:

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

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

        【讨论】:

          【解决方案14】:

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

          【讨论】:

            【解决方案15】:

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

            【讨论】:

              【解决方案16】:

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

              android:backgroundTint="@color/accent"
              

              你可以简单地说..

              android:background="@color/accent"
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2020-11-10
                • 2015-11-04
                • 2010-12-01
                • 2013-10-07
                • 2021-12-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多