【问题标题】:Material effect on button with background color具有背景颜色的按钮的材质效果
【发布时间】:2014-12-28 10:58:03
【问题描述】:

我正在使用 Android v21 支持库。

我创建了一个带有自定义背景颜色的按钮。当我使用背景颜色时,波纹、显示等 Material 设计效果消失了(点击时的高度除外)。

 <Button
 style="?android:attr/buttonStyleSmall"
 android:background="?attr/colorPrimary"
 android:textColor="@color/white"
 android:textAllCaps="true"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:text="Button1"
 />

下面是一个普通的按钮,效果很好。

<Button
 style="?android:attr/buttonStyleSmall"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:textAllCaps="true"
 android:text="Button1"
/>

【问题讨论】:

  • 这是因为你用纯色替换了所有漂亮的材质效果。至于如何在保持 Material 效果的同时正确地为按钮着色,目前还没有人能够弄清楚。
  • @SweetWisher 当我更改背景颜色时,按钮中没有应用波纹和其他效果。
  • @NathanWalters 但是默认的灰色很难看。 :-(
  • 相信我,我知道......我们将非常感谢那些想出如何正确执行此操作的人。

标签: android android-5.0-lollipop


【解决方案1】:

当您使用android:background 时,您正在用空白颜色替换按钮的大部分样式和外观。

更新:AppCompatversion 23.0.0 release 开始,有一个新的Widget.AppCompat.Button.Colored 样式,它使用主题的colorButtonNormal 为禁用颜色,colorAccent 为启用颜色.

这允许您直接通过

将其应用到您的按钮
<Button
  ...
  style="@style/Widget.AppCompat.Button.Colored" />

如果您需要自定义colorButtonNormalcolorAccent,您可以使用ThemeOverlay,如按钮上的this pro-tipandroid:theme 中所述。

上一个答案

您可以在 v21 目录中使用可绘制对象作为背景,例如:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?attr/colorControlHighlight">
    <item android:drawable="?attr/colorPrimary"/>
</ripple>

这将确保您的背景颜色为?attr/colorPrimary,并使用默认的?attr/colorControlHighlight 使用默认的波纹动画(如果您愿意,也可以在主题中设置)。

注意:您必须为低于 v21 创建一个自定义选择器:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/primaryPressed" android:state_pressed="true"/>
    <item android:drawable="@color/primaryFocused" android:state_focused="true"/>
    <item android:drawable="@color/primary"/>
</selector>

假设您对默认、按下和聚焦状态有一些您想要的颜色。就个人而言,我在被选中的过程中截取了一个涟漪的屏幕截图,并将主要/聚焦状态从中拉出来。

【讨论】:

  • 不错的答案!正是我想要的,但是在项目决定在 drawable-v21 中识别可绘制对象之前需要清理和重建。
  • @ianhanniballake 我想知道如何结合这种工作技术而不会丢失那些按钮中的圆角自定义
  • @ianhanniballake 只是一个评论,可以在 下的波纹中绘制,不能是透明颜色。在这种情况下,不会显示波纹。我花了一段时间才意识到这一点。
  • 使用 appcompat 23.1.1 和 API 22,禁用和启用状态都采用主题的 colorButtonNormal 颜色。
【解决方案2】:

还有另一种简单的解决方案可以为“平面”按钮提供自定义背景,同时保持其“材质”效果。

  1. 将您的按钮放在 ViewGroup 中,并在此处设置所需的背景
  2. 将当前主题中的 selectableItemBackground 设置为按钮的背景 (API >=11)

即:

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/blue">
    <Button
        style="?android:attr/buttonStyleSmall"
        android:background="?android:attr/selectableItemBackground"
        android:textColor="@android:color/white"
        android:textAllCaps="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="Button1"
        />
</FrameLayout>

可用于Flat 按钮,它适用于 API >=11,您将在 >=21 设备上获得涟漪效应,在 AppCompat 更新以支持那里的涟漪之前,将常规按钮保持在 21 之前。

您也可以将selectableItemBackgroundBorderless 用于>=21 个按钮。

【讨论】:

  • 您确实是开箱即用 :-) 虽然这是这样做的一种方法,但它可能会增加代码耦合,并且推荐使用样式。
  • 这会创建一个带有彩色背景的平面按钮,是的。但是创建的按钮看起来像一个正方形,没有圆角和阴影效果。
  • @SanketBerde 没错。因为这就是“扁平”按钮。
  • 原来的问题没有提到flat。顺便说一句,如果您的解决方案中有一个 父级而不是 ,则生成的按钮将被抬起并有阴影。这甚至适用于棒棒糖之前的版本。
  • @SanketBerde 很高兴了解CardView 方法,感谢分享!
【解决方案3】:

这是一种简单且向后兼容的方法,可以为具有自定义背景的凸起按钮提供波纹效果。

你的布局应该是这样的

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_custom_background"
    android:foreground="?android:attr/selectableItemBackground"/>

【讨论】:

  • 这是完成此任务的最简单的方法。很好的答案。
  • api 21+ 但不工作。应用于具有可点击真实、背景 - 不同颜色、指定前景的线性布局。
  • 由于Button是TextView而不是FrameLayout,所以foreground在23之前没有效果。google.com/…
  • 不错!我什至不知道“前景”是一回事!
  • 像魅力一样工作..!
【解决方案4】:

我今天在玩 v22 库时遇到了这个问题。

假设您正在使用样式,您可以设置colorButtonNormal 属性,并且按钮将默认使用该颜色。

<style name="AppTheme" parent="BaseTheme">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/primaryColor</item>
    <item name="colorPrimaryDark">@color/primaryColorDark</item>
    <item name="colorAccent">@color/accentColor</item>
    <item name="colorButtonNormal">@color/primaryColor</item>
</style>

除此之外,您仍然可以为按钮制作样式,然后如果您需要各种颜色(尚未测试,只是推测),则为每个按钮使用该样式。

记得在v21 样式中的项目名称前添加android:

【讨论】:

  • 对于各种彩色按钮,请参阅其他 Robert 的回答:stackoverflow.com/a/31825439/1617737
  • 现在设置了背景颜色,是否还有我可以在上面的代码块中使用的通用属性来指定按钮文本颜色?
【解决方案5】:

@ianhanniballake 的回答绝对正确且简单。但我花了几天时间才明​​白。对于不明白他的答案的人,这里有更详细的实现

<Button
        android:id="@+id/btn"
        style="@style/MaterialButton"
        ... />


<style name="MaterialButton" parent="Widget.AppCompat.Button.Colored">
    <item name="android:theme">@style/Theme.MaterialButton</item>
   ...
</style>


<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

===或===

<Button
        android:id="@+id/btn"
        style="@style/Widget.AppCompat.Button.Colored"
        android:theme="@style/Theme.MaterialButton" />

<style name="Theme.MaterialButton" parent="YourTheme">
    <item name="colorAccent">@color/yourAccentColor</item>
    <item name="colorButtonNormal">@color/yourButtonNormalColor</item>
</style>

【讨论】:

  • 您的回答对我来说是最后一块拼图。也可以在基本主题@style/AppTheme 中写colorButtonNormal。这为 AppCompat 提供了一个默认颜色,以相应地为按钮着色。然后可以使用您的答案单独为视图设置主题。
  • android:theme="Theme.MaterialButton"还是android:theme="@style/Theme.MaterialButton"
  • @osrl 这是android:theme="@style/Theme.MaterialButton"。谢谢你的正确。
【解决方案6】:

使用 AppCompat (22.1.1+),您可以添加如下样式:

<style name="MyGreenButton">
    <item name="colorButtonNormal">#009900</item>
</style>

只需应用样式即可使用它:

<android.support.v7.widget.AppCompatButton
    style="@style/MyGreenButton"
    android:layout_width="match_width"
    android:layout_height="wrap_content"
    android:text="A Green Button"
    />

以编程方式更改颜色,我发现更新颜色的唯一方法(在 API 15 或 16 上)是使用“背景色调列表”。而且它不会删除 API 21 设备上漂亮的径向动画:

ColorStateList colorStateList = new ColorStateList(new int[][] {{0}}, new int[] {0xFF009900}); // 0xAARRGGBB
button.setSupportBackgroundTintList(colorStateList);

因为 button.setBackground(...)button.getBackground().mutate().setColorFilter(...) 不会像在 API 21 上那样更改 API 15 和 16 上的按钮颜色。

【讨论】:

  • 非常感谢,它对我来说非常有效(即使在 xml 布局中使用 Button 作为 AppCompat inflater 将其替换为 AppCompatButton)
  • 使用ColorStateList.valueOf( ... ) 构造一个只有一种颜色的简单ColorStateList
  • colorAccent 和ippleColor 在样式中不起作用
  • 感谢您的这篇文章。什么对我有用:ViewCompat.setBackgroundTintList(myButton, ColorStateList.valueOf(myColor);setSupportBackgroundTintList 的 Javadoc 说它应该这样调用。
【解决方案7】:

我使用了 backgroundTint 和前景:

<Button
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:backgroundTint="@color/colorAccent"
    android:foreground="?android:attr/selectableItemBackground"
    android:textColor="@android:color/white"
    android:textSize="10sp"/>

【讨论】:

  • afaik 没有必要设置 foreground 属性,因为 backgroundTint 不会覆盖标准波纹
【解决方案8】:

我来这篇文章是为了寻找一种方法来为我的 ListView 项目设置背景色,同时保持波纹。

我只是将我的颜色添加为背景,将 selectableItemBackground 添​​加为前景:

<style name="my_list_item">
    <item name="android:background">@color/white</item>
    <item name="android:foreground">?attr/selectableItemBackground</item>
    <item name="android:layout_height">@dimen/my_list_item_height</item>
</style>

它就像一个魅力。我想同样的技术也可以用于按钮。祝你好运:)

【讨论】:

    【解决方案9】:

    使用backgroundTint 而不是background

    【讨论】:

    【解决方案10】:

    如果你对 ImageButton 感兴趣,可以试试这个简单的东西:

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_button"
        android:background="?attr/selectableItemBackgroundBorderless"
    />
    

    【讨论】:

      【解决方案11】:

      v22.1appcompat-v7 引入了一些新的可能性。现在可以仅将特定主题分配给一个视图。

      不推荐使用 app:theme 来设置工具栏的样式。您现在可以使用 android:theme 用于所有 API 级别 7 及更高级别设备上的工具栏和 android:theme 支持 API 级别 11 及更高级别的所有小部件 设备。

      因此,我们不是在全局主题中设置所需的颜色,而是创建一个新主题并将其仅分配给Button

      示例:

      <style name="MyColorButton" parent="Theme.AppCompat.Light.DarkActionBar">
              <item name="colorButtonNormal">@color/myColor</item>
      </style>
      

      并使用这种风格作为Button的主题

      <Button
       style="?android:attr/buttonStyleSmall"
       android:layout_width="fill_parent"
       android:layout_height="wrap_content"
       android:text="Button1"
       android:theme="@style/MyColorButton"/>
      

      【讨论】:

        【解决方案12】:

        如果您可以使用第三方库,请查看traex/RippleEffect。它允许您通过几行代码将波纹效果添加到 ANY 视图。您只需要在您的 xml 布局文件中包装您想要使用 com.andexert.library.RippleView 容器产生涟漪效果的元素。

        作为额外的奖励,它需要 Min SDK 9,因此您可以在不同操作系统版本之间保持设计一致性。

        这是从库的 GitHub 存储库中获取的示例:

        <com.andexert.library.RippleView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:rv_centered="true">
        
            <ImageView
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:src="@android:drawable/ic_menu_edit"
                android:background="@android:color/holo_blue_dark"/> 
        
        </com.andexert.library.RippleView>
        

        您可以通过在 RippleView 元素中添加此属性来更改波纹颜色:app:rv_color="@color/my_fancy_ripple_color

        【讨论】:

          【解决方案13】:
          <android.support.v7.widget.AppCompatButton
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              app:backgroundTint="#fff"
              android:textColor="#000"
              android:text="test"/>
          

          使用

          xmlns:app="http://schemas.android.com/apk/res-auto"
          

          而且颜色会在棒棒糖前接受

          【讨论】:

            【解决方案14】:

            Alex Lockwood 的精彩教程中解释了两种方法:http://www.androiddesignpatterns.com/2016/08/coloring-buttons-with-themeoverlays-background-tints.html:

            方法 #1:使用 ThemeOverlay 修改按钮的背景颜色

            <!-- res/values/themes.xml -->
            <style name="RedButtonLightTheme" parent="ThemeOverlay.AppCompat.Light">
                <item name="colorAccent">@color/googred500</item>
            </style>
            

            <Button
                style="@style/Widget.AppCompat.Button.Colored"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:theme="@style/RedButtonLightTheme"/>
            

            方法 #2:设置 AppCompatButton 的背景色

            <!-- res/color/btn_colored_background_tint.xml -->
            <selector xmlns:android="http://schemas.android.com/apk/res/android">
            
                <!-- Disabled state. -->
                <item android:state_enabled="false"
                      android:color="?attr/colorButtonNormal"
                      android:alpha="?android:attr/disabledAlpha"/>
            
                <!-- Enabled state. -->
                <item android:color="?attr/colorAccent"/>
            
            </selector>
            

            <android.support.v7.widget.AppCompatButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:backgroundTint="@color/btn_colored_background_tint"/>
            

            【讨论】:

              【解决方案15】:

              以编程方式应用颜色:

              if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
              
                  ColorStateList colorStateListRipple = new ColorStateList(
                          new int[][] {{0}},
                          new int[] {Color.WHITE} // ripple color
                          );
              
                  RippleDrawable rippleDrawable = (RippleDrawable) myButton.getBackground();
                  rippleDrawable.setColor(colorStateListRipple);
                  myButton.setBackground(rippleDrawable); // applying the ripple color
              }
              
              ColorStateList colorStateList = new ColorStateList(
                      new int[][]{
                              new int[]{android.R.attr.state_pressed}, // when pressed
                              new int[]{android.R.attr.state_enabled}, // normal state color
                              new int[]{} // normal state color
                      },
                      new int[]{
                              Color.CYAN, // when pressed
                              Color.RED, // normal state color
                              Color.RED // normal state color
                      }
              );
              
              ViewCompat.setBackgroundTintList(myButton, colorStateList); // applying the state colors
              

              【讨论】:

                【解决方案16】:

                以编程方式:

                 myMaterialButton.setRippleColor(ColorStateList.valueOf(Color.RED));
                

                例如:

                 MaterialButton myMaterialButton = new MaterialButton(this);
                 myMaterialButton.setLayoutParams(myButtonParams);
                 myMaterialButton.setBackgroundColor(Color.GRAY);
                 myMaterialButton.setRippleColor(ColorStateList.valueOf(Color.RED));
                   
                

                【讨论】:

                  【解决方案17】:

                  我试过了:

                  android:backgroundTint:"@color/mycolor"
                  

                  而不是更改背景属性。 这不会消除材质效果。

                  【讨论】:

                  • 这不适用于棒棒糖之前的设备(70% 的市场份额)。实际上它已经被向后移植了,但是到目前为止,Android Studio 在没有 android 前缀的情况下使用它时仍然显示错误。
                  猜你喜欢
                  • 2020-11-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-11-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-08-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多