Android中着色button与材质devise和AppCompat
在今天AppCompat
更新出来之前,我可以改变Android L中button的颜色,但不能更改旧版本的颜色。 包括新的AppCompat更新后,我无法更改任何版本的颜色,当我尝试button只是消失。 有谁知道如何更改button的颜色?
下面的图片显示了我想要实现的:
白色的button是默认的,红色的是我想要的。
这是我以前在修改styles.xml
button的颜色时所做的:
<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.DarkActionBar
为Theme.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.Colored
button上的文本颜色默认为白色!
但似乎有一个问题,当你禁用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));
使用最新的支持库,您可以从AppCompatActivity
inheritance您的活动,因此它将使您的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中却没有。 该项目configurationcompileSdkVersion
和targetSdkVersion
为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.Button , Base.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" />