Android中着色button与材质devise和AppCompat

在今天AppCompat更新出来之前,我可以改变Android L中button的颜色,但不能更改旧版本的颜色。 包括新的AppCompat更新后,我无法更改任何版本的颜色,当我尝试button只是消失。 有谁知道如何更改button的颜色?

下面的图片显示了我想要实现的:

显示所需结果的图片

白色的button是默认的,红色的是我想要的。

这是我以前在修改styles.xmlbutton的颜色时所做的:

 <item name="android:colorButtonNormal">insert color here</item> 

并dynamic地做到这一点:

 button.getBackground().setColorFilter(getResources().getColor(insert color here), PorterDuff.Mode.MULTIPLY); 

另外,我也从@android:style/Theme.Material.Light.DarkActionBarTheme.AppCompat.Light.DarkActionBar

支持库修订版22(2015年3月13日,星期五)正式修复。 查看相关的google代码问题:

https://issuetracker.google.com/issues/37008632

用法示例

theme.xml:

 <item name="colorButtonNormal">@color/button_color</item> 

V21 / theme.xml

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

编辑(22.06.2016):

在发布原始响应后, Appcompat库开始支持材质button。 在这篇文章中,您可以看到凸起和平面button的最简单的实现。

原始答案:

由于该AppCompat不支持该button,你可以使用xml作为背景。 为了做到这一点,我看了一下Android的源代码,并find了样式材质button的相关文件。

1 – 从源代码看原始button的实现。

看看android源代码上的btn_default_material.xml 。

您可以将文件复制到您的项目drawable-v21文件夹中。 但是不要碰这里的颜色。 您需要更改的文件是第二个文件。

可绘制-V21 / custom_btn.xml

 <ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="?attr/colorControlHighlight"> <item android:drawable="@drawable/btn_default_mtrl_shape" /> </ripple> 

2 – 获取原始材料button的形状

当你意识到在这个drawable中有一个形状,你可以在这个源代码文件中find它 。

 <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="?attr/colorButtonNormal" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> 

3 – 获取材料button的尺寸

在这个文件中,您可以从文件中find一些使用的维度。 您可以复制整个文件并放入您的文件夹。 这对于在所有button上应用相同的大小(在材质button中使用)是很重要的

4 – 为旧版本创build另一个可绘制文件

对于旧版本,你应该有另外一个同名的drawable。 我直接把项目内联而不是引用。 你可能想引用它们。 但是,最重要的是材料button的原始尺寸。

绘制/ custom_btn.xml

  <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- pressed state --> <item android:state_pressed="true"> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/PRESSED_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> <!-- focused state --> <item android:state_focused="true"> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/FOCUSED_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> <!-- normal state --> <item> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/NORMAL_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> </selector> 

结果

你的button会对棒棒糖设备产生连锁反应。 旧版本除了涟漪效应外,其他button都是完全一样的。 但是既然你为不同的状态提供了drawables,他们也会响应触摸事件(如旧的方式)。

这已经在AppCompat库的v23.0.0中增加了更多的主题,包括

Widget.AppCompat.Button.Colored

首先包括appCompat依赖关系,如果你还没有

 compile('com.android.support:appcompat-v7:23.0.0') { exclude group: 'com.google.android', module: 'support-v4' } 

现在,因为您需要使用应用程序compat的v23,您还需要定位到SDK-v23!

  compileSdkVersion = 23 targetSdkVersion = 23 

在你的values/theme

 <item name="android:buttonStyle">@style/BrandButtonStyle</item> 

在你的values/style

 <style name="BrandButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@color/yourButtonColor</item> <item name="android:textColor">@color/White</item> </style> 

在你的values-v21/style

 <style name="BrandButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="android:colorButtonNormal">@color/yourButtonColor</item> <item name="android:textColor">@color/White</item> </style> 

由于您的button主题基于Widget.AppCompat.Button.Coloredbutton上的文本颜色默认为白色!

但似乎有一个问题,当你禁用button,button将改变其颜色为浅灰色,但文字颜色将保持白色!

一个解决方法是专门设置button上的文本颜色为白色! 正如我上面所示的样式所做的那样。

现在你可以简单地定义你的button,让AppCompat做其余的:)

 <Button android:layout_width="200dp" android:layout_height="48dp" /> 

禁用状态 禁用状态

启用状态 启用状态

在Android支持库22.1.0中,Google使Button Tint感知。 所以,另一种自定义button背景颜色的方法是使用backgroundTint属性。

例如,

 <Button android:id="@+id/add_remove_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:backgroundTint="@color/bg_remove_btn_default" android:textColor="@android:color/white" tools:text="Remove" /> 

要支持彩色button,请使用最新的AppCompat库(> 23.2.1 ):

膨胀 – XML

AppCompat小工具:

 android.support.v7.widget.AppCompatButton 

AppCompat风格:

 style="@style/Widget.AppCompat.Button.Colored" 

NB! 在xml中设置自定义颜色:使用attr: app而不是android

(使用alt+enter或声明xmlns:app="http://schemas.android.com/apk/res-auto"使用app

app :backgroundTint =“@ color / your_custom_color”

例:

 <android.support.v7.widget.AppCompatButton style="@style/Widget.AppCompat.Button.Colored" app:backgroundTint="@color/your_custom_color" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Colored Button"/> 

或以编程方式设置 – JAVA

  ViewCompat.setBackgroundTintList(your_colored_button, ContextCompat.getColorStateList(getContext(),R.color.your_custom_color)); 

使用最新的支持库,您可以从AppCompatActivityinheritance您的活动,因此它将使您的Button AppCompatButton并让您有机会使用android:theme="@style/SomeButtonStyle"为布局上的每个button添加样式的颜色, SomeButtonStyle是:

 <style name="SomeButtonStyle" parent="@android:style/Widget.Button"> <item name="colorButtonNormal">@color/example_color</item> </style> 

在2.3.7,4.4.1,5.0.2中为我工作

如果你想下面的风格

在这里输入图像描述

添加这个样式你的button

 style="@style/Widget.AppCompat.Button.Borderless.Colored" 

如果你想要这种风格

在这里输入图像描述

添加下面的代码

 style="@style/Widget.AppCompat.Button.Colored" 

答案是主题不是风格

问题是button颜色是坚持主题的colorButtonNormal。 我试图以许多不同的方式改变风格,但没有运气。 所以我改变了button的主题

使用colorButtonNormal和colorPrimary创build主题:

 <style name="ThemeAwesomeButtonColor" parent="AppTheme"> <item name="colorPrimary">@color/awesomePrimaryColor</item> <item name="colorButtonNormal">@color/awesomeButtonColor</item> </style> 

在button中使用此主题

 <Button android:id="@+id/btn_awesome" style="@style/AppTheme.Button" android:theme="@style/ThemeAwesomeButtonColor" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/btn_awesome"/> 

“AppTheme.Button”可以是任何东西扩展button样式就像这里我使用原色为文本颜色:

 <style name="AppTheme.Button" parent="Base.Widget.AppCompat.Button"> ... <item name="android:textColor">?attr/colorPrimary</item> ... </style> 

并且您可以获得与材料devise兼容的任何颜色的button。

我刚刚创build了一个android库,允许您轻松修改button颜色和纹波颜色

https://github.com/xgc1986/RippleButton

 <com.xgc1986.ripplebutton.widget.RippleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn" android:text="Android button modified in layout" android:textColor="@android:color/white" app:buttonColor="@android:color/black" app:rippleColor="@android:color/white"/> 

你不需要为每个你想要不同颜色的button创build一个样式,允许你随机的自定义颜色

这个工作在android + 4.0中使用appcompat-v7:22.2.0

在你的styles.xml中

 <style name="Button.Tinted" parent="Widget.AppCompat.Button"> <item name="colorButtonNormal">YOUR_TINT_COLOR</item> <item name="colorControlHighlight">@color/colorAccent</item> <item name="android:textColor">@android:color/white</item> </style> 

在你的布局文件中

 <Button android:id="@+id/but_next" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/but_continue" android:theme="@style/Button.Tinted" /> 

布局:

 <android.support.v7.widget.AppCompatButton style="@style/MyButton" ... /> 

styles.xml:

 <style name="MyButton" parent="Widget.AppCompat.Button.Colored"> <item name="backgroundTint">@color/button_background_selector</item> <item name="android:textColor">@color/button_text_selector</item> </style> 

颜色/ button_background_selector.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:color="#555555"/> <item android:color="#00ff00"/> </selector> 

颜色/ button_text_selector.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:color="#888888"/> <item android:color="#ffffff"/> </selector> 

对于那些在这里使用ImageButton ,是这样做的:

在style.xml中:

 <style name="BlueImageButton" parent="Base.Widget.AppCompat.ImageButton"> <item name="colorButtonNormal">@color/primary</item> <item name="android:tint">@color/white</item> </style> 

在v21 / style.xml中:

 <style name="BlueImageButton" parent="Widget.AppCompat.ImageButton"> <item name="android:colorButtonNormal">@color/primary</item> <item name="android:tint">@color/white</item> </style> 

然后在你的布局文件中:

 <android.support.v7.widget.AppCompatImageButton android:id="@+id/my_button" android:theme="@style/BlueImageButton" android:layout_width="42dp" android:layout_height="42dp" android:layout_gravity="center_vertical" android:src="@drawable/ic_check_black_24dp" /> 

如果您使用colorButtonNormal的样式解决scheme,不要忘记从Widget.AppCompat.Button.Coloredinheritance,所以涟漪效应工作;)

喜欢

 <style name="CustomButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@android:color/white</item> </style> 

如果您只想要“Flat”材质button,则可以使用selectableItemBackground属性自定义其背景,如此处所述。

对我来说,问题是在Android 5.0中, android:colorButtonNormal没有任何效果,实际上没有来自主题的项目(比如android:colorAccent ),但是在Android 4.4.3中却没有。 该项目configurationcompileSdkVersiontargetSdkVersion为22,所以我做了所有的变化@穆罕默德Alfaifi Sugessted,但最终,我已经注意到,问题是buildToolsVersion ,没有更新。 一旦我改变到23.0.1 ,一切都开始正常工作。 现在, android:colorButtonNormal仍然没有效果,但至lessbutton反应到android:colorAccent ,这对我来说是可以接受的。

我希望这个提示可以帮助某人。 注意:我已经将样式直接应用到button,因为button的android:theme=[...]也没有效果。

一种方法可以让你指向风格而不是主题所有的应用程序中的button都是一样的。
在themes.xml中添加一个主题

  <style name="Theme.MyApp.Button.Primary.Blue" parent="Widget.AppCompat.Button"> <item name="colorButtonNormal">@color/someColor</item> <item name="android:textColorPrimary">@android:color/white</item> </style> 

现在在styles.xml中添加

  <style name="MyApp.Button.Primary.Blue" parent=""> <item name="android:theme">@style/Theme.MyApp.Button.Primary.Blue</item> </style> 

现在在你的布局中,只需指向Button中的STYLE即可

  <Button ... style="@style/MyApp.Button.Primary.Blue" ... /> 

UPDATE

使用devise支持库(23.2.0)appcompatwidgets如下

在Android支持库22.1中

这是膨胀布局时自动完成的 – 用AppCompatButtonreplaceButton,用AppCompatTextViewreplaceTextView等,以确保每个都可以支持着色。 在这个版本中,那些色彩感知的小部件现在是公开的,允许你保持着色支持,即使你需要inheritance一个支持的小部件。

色调感知小部件的完整列表:

 AppCompatAutoCompleteTextView AppCompatButton AppCompatCheckBox AppCompatCheckedTextView AppCompatEditText AppCompatMultiAutoCompleteTextView AppCompatRadioButton AppCompatRatingBar AppCompatSpinner AppCompatTextView 

预棒棒糖设备的材料devise

AppCompat(又名ActionBarCompat)作为Gingerbread上运行的设备的Android 4.0 ActionBar API的后端开始,在后端实现和框架实现之上提供了一个通用的API层。 AppCompat v21提供了一个与Android 5.0最新的API和function集


我其实不想改变我的自定义button样式,但不幸的是,他们不工作了。

我的应用程序有一个9的minSdkVersion和一切工作。

我不知道为什么,但因为我删除了android:之前buttonStyle它似乎再次工作

现在=工作:

<item name="buttonStyle">@style/ButtonmyTime</item>

之前=只是灰色的材料button:

<item name="android:buttonStyle">@style/ButtonmyTime</item>

我没有新的Android版本spezial文件夹,因为我的button是相当平坦的,他们应该看起来在所有的Android版本相同。

也许有人可以告诉我,为什么我不得不删除“android:”ImageButton仍然与“android:”

 <item name="android:imageButtonStyle">@style/ImageButtonmyTimeGreen</item> 

2天后寻找答案,button主题不适合我API <21。

我唯一的解决scheme是重写AppCompatButton不仅与基本应用程序主题“colorButtonNormal”着色,而且视图backgroundTint是这样的:

 public class AppCompatColorButton extends AppCompatButton { public AppCompatColorButton(Context context) { this(context, null); } public AppCompatColorButton(Context context, AttributeSet attrs) { this(context, attrs, android.support.v7.appcompat.R.attr.buttonStyle); } public AppCompatColorButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (TintManager.SHOULD_BE_USED) { setSupportBackgroundTintList(createButtonColorStateList(getContext(), attrs, defStyleAttr)); } } static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled}; static final int[] FOCUSED_STATE_SET = new int[]{android.R.attr.state_focused}; static final int[] PRESSED_STATE_SET = new int[]{android.R.attr.state_pressed}; static final int[] EMPTY_STATE_SET = new int[0]; private ColorStateList createButtonColorStateList(Context context, AttributeSet attrs, int defStyleAttr) { final int[][] states = new int[4][]; final int[] colors = new int[4]; int i = 0; final int themeColorButtonNormal = ThemeUtils.getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorButtonNormal); /*TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.backgroundTint }, defStyleAttr, 0); final int colorButtonNormal = a.getColor(0, themeColorButtonNormal);*/ TypedArray a = context.obtainStyledAttributes(attrs, android.support.v7.appcompat.R.styleable.View, defStyleAttr, 0); final int colorButtonNormal = a.getColor(android.support.v7.appcompat.R.styleable.View_backgroundTint, themeColorButtonNormal); a.recycle(); final int colorControlHighlight = ThemeUtils.getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorControlHighlight); // Disabled state states[i] = DISABLED_STATE_SET; colors[i] = ThemeUtils.getDisabledThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorButtonNormal); i++; states[i] = PRESSED_STATE_SET; colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal); i++; states[i] = FOCUSED_STATE_SET; colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal); i++; // Default enabled state states[i] = EMPTY_STATE_SET; colors[i] = colorButtonNormal; i++; return new ColorStateList(states, colors); } } 

你可以这样定义你的Button颜色:

 <com.example.views.AppCompatColorButton android:layout_width="match_parent" android:layout_height="wrap_content" android:backgroundTint="#ffff0000" app:backgroundTint="#ffff0000" android:text="Button" android:textColor="@android:color/white" /> 

改变一个button的颜色

 ViewCompat.setBackgroundTintList(button, getResources().getColorStateList(R.color.colorId)); 

这个答案帮助我到达了一个答案https://stackoverflow.com/a/30277424/3075340

我使用这个实用的方法来设置一个button的背景色。 它适用于预棒棒糖设备:

 // Set button background tint programmatically so it is compatible with pre-lollipop devices. public static void setButtonBackgroundTintAppCompat(Button button, ColorStateList colorStateList){ Drawable d = button.getBackground(); if (button instanceof AppCompatButton) { // appcompat button replaces tint of its drawable background ((AppCompatButton)button).setSupportBackgroundTintList(colorStateList); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Lollipop button replaces tint of its drawable background // however it is not equal to d.setTintList(c) button.setBackgroundTintList(colorStateList); } else { // this should only happen if // * manually creating a Button instead of AppCompatButton // * LayoutInflater did not translate a Button to AppCompatButton d = DrawableCompat.wrap(d); DrawableCompat.setTintList(d, colorStateList); button.setBackgroundDrawable(d); } } 

如何在代码中使用:

 Utility.setButtonBackgroundTintAppCompat(myButton, ContextCompat.getColorStateList(mContext, R.color.your_custom_color)); 

这样,你不必指定一个ColorStateList,如果你只是想改变背景的色调,没有什么更多,但保持漂亮的button效果,而不是。

如果您想使用Widget.AppCompat.ButtonBase.Widget.AppCompat.Button.Colored等AppCompat样式, 需要使用支持库中兼容视图的这些样式。

下面的代码不适用于pre-lolipop设备:

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

您需要使用AppCompatButton来启用AppCompat样式:

 <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:theme="@style/Widget.AppCompat.Button" />