Standard Android Button with a different color
我想稍微更改标准Android按钮的颜色,以便更好地匹配客户的品牌。
到目前为止,我发现这样做的最好方法是将
1 2 3 4 5 6 | <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/red_button_pressed" /> <item android:state_focused="true" android:drawable="@drawable/red_button_focus" /> <item android:drawable="@drawable/red_button_rest" /> </selector> |
但这样做需要我实际上为我想要自定义的每个按钮创建三个不同的drawable(一个用于静止按钮,一个用于聚焦,一个用于按下)。 这似乎比我需要的更复杂,更干燥。
我真正想做的就是对按钮应用某种颜色转换。 是否有更简单的方法来改变按钮的颜色而不是我正在做的事情?
我发现这一切都可以很容易地在一个文件中完成。将类似下面的代码放在名为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <shape> <gradient android:startColor="@color/yellow1" android:endColor="@color/yellow2" android:angle="270" /> <stroke android:width="3dp" android:color="@color/grey05" /> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape> </item> <item android:state_focused="true"> <shape> <gradient android:endColor="@color/orange4" android:startColor="@color/orange5" android:angle="270" /> <stroke android:width="3dp" android:color="@color/grey05" /> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape> </item> <item> <shape> <gradient android:endColor="@color/blue2" android:startColor="@color/blue25" android:angle="270" /> <stroke android:width="3dp" android:color="@color/grey05" /> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape> </item> </selector> |
继Tomasz的回答之后,您还可以使用PorterDuff乘法模式以编程方式设置整个按钮的阴影。这将改变按钮颜色而不仅仅是色调。
如果您使用标准灰色阴影按钮开头:
1 | button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY); |
会给你一个红色阴影按钮,
1 | button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY); |
会给你一个绿色阴影按钮等,其中第一个值是十六进制格式的颜色。
它的工作原理是将当前按钮颜色值乘以颜色值。我相信你可以用这些模式做更多的事情。
迈克,您可能对彩色滤光片感兴趣。
一个例子:
1 | button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000)); |
试试这个来达到你想要的颜色。
这是我的解决方案,从API 15开始完美运行。此解决方案保留所有默认按钮单击效果,如材料
你需要做的就是:
1)创建仅更改
1 2 3 | <style name="Facebook.Button" parent="ThemeOverlay.AppCompat"> <item name="colorAccent">@color/com_facebook_blue</item> </style> |
I recommend using
ThemeOverlay.AppCompat or your mainAppTheme as parent, to keep the rest of your styles.
2)将这两行添加到
1 2 | style="@style/Widget.AppCompat.Button.Colored" android:theme="@style/Facebook.Button" |
Sometimes your new
colorAccent isn't showing in Android Studio Preview, but when you launch your app on the phone, the color will be changed.
示例按钮小部件
1 2 3 4 5 6 7 8 9 | <Button android:id="@+id/sign_in_with_facebook" style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/sign_in_facebook" android:textColor="@android:color/white" android:theme="@style/Facebook.Button" /> |
您现在还可以使用appcompat-v7的AppCompatButton和
1 2 3 4 5 | <android.support.v7.widget.AppCompatButton xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" app:backgroundTint="#ffaa00"/> |
我喜欢@conjugatedirection和@Tomasz先前答案中的滤色器建议;但是,我发现到目前为止提供的代码并不像我预期的那样容易应用。
首先,没有提到应用和清除滤色器的位置。有可能还有其他好的地方可以做到这一点,但我想到的是一个OnTouchListener。
从我对原始问题的解读,理想的解决方案将是不涉及任何图像的解决方案。如果这是你的目标,那么使用@emmby中的custom_button.xml接受的答案可能比彩色滤镜更合适。在我的例子中,我从一个UI设计师的png图像开始,按钮应该是什么样子。如果我将按钮背景设置为此图像,则默认高光反馈将完全丢失。此代码使用程序化变暗效果替换该行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 0x6D6D6D sets how much to darken - tweak as desired setColorFilter(v, 0x6D6D6D); break; // remove the filter when moving off the button // the same way a selector implementation would case MotionEvent.ACTION_MOVE: Rect r = new Rect(); v.getLocalVisibleRect(r); if (!r.contains((int) event.getX(), (int) event.getY())) { setColorFilter(v, null); } break; case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: setColorFilter(v, null); break; } return false; } private void setColorFilter(View v, Integer filter) { if (filter == null) v.getBackground().clearColorFilter(); else { // To lighten instead of darken, try this: // LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter); LightingColorFilter darken = new LightingColorFilter(filter, 0x000000); v.getBackground().setColorFilter(darken); } // required on Android 2.3.7 for filter change to take effect (but not on 4.0.4) v.getBackground().invalidateSelf(); } }); |
我把它作为一个单独的类提取出来应用于多个按钮 - 显示为匿名内部类只是为了得到这个想法。
如果您使用XML制作颜色按钮,则可以通过在单独的文件中指定聚焦和按下状态并重复使用来使代码更清晰。我的绿色按钮看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:drawable="@drawable/button_focused"/> <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/> <item> <shape> <gradient android:startColor="#ff00ff00" android:endColor="#bb00ff00" android:angle="270" /> <stroke android:width="1dp" android:color="#bb00ff00" /> <corners android:radius="3dp" /> <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" /> </shape> </item> </selector> |
适用于任何Android版本的最短解决方案:
1 2 | <Button app:backgroundTint="@color/my_color" |
备注/要求:
-
使用
app: 命名空间而不是android: 命名空间! -
appcompat版本> 24.2.0
依赖{
编译'com.android.support:appcompat-v7:25.3.1'
}
说明:
我正在使用这种方法
style.xml
1 2 3 4 5 6 7 8 9 10 11 12 | <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:colorPrimaryDark">#413152</item> <item name="android:colorPrimary">#534364</item> <item name="android:colorAccent">#534364</item> <item name="android:buttonStyle">@style/MyButtonStyle</item> </style> <style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="android:colorButtonNormal">#534364</item> <item name="android:textColor">#ffffff</item> </style> |
从上面可以看出,我正在为我的按钮使用自定义样式。按钮颜色对应于强调颜色。我觉得这比设置
以这种方式使用它:
1 | buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY); |
现在有一种更简单的方法:android-holo-colors.com
它可以让你轻松改变所有holo drawables(纽扣,旋转器......)的颜色。您选择颜色,然后下载包含所有分辨率的drawable的zip文件。
在
DroidUX组件库有一个
您还可以使用此在线工具自定义按钮http://angrytools.com/android/button/并使用
您可以将按钮的主题设置为此
1 2 3 4 | <style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@color/HEXColor</item> <item name="android:textColor">@color/HEXColor</item> </style> |
一种简单的方法是只定义一个自定义Button类,它接受你想要的所有属性,如半径,渐变,按下的颜色,正常颜色等,然后??在XML布局中使用它而不是使用XML设置背景。这是一个样本
如果您有许多具有相同属性(如半径,选定颜色等)的按钮,则此功能非常有用。您可以自定义继承按钮以处理这些附加属性。
结果(未使用背景选择器)。
普通按钮
按下按钮
它很简单..在你的项目中添加这个依赖项并创建一个按钮
1.任何形状
2.任何颜色
3.任何边界
4.具有物质效应
https://github.com/manojbhadane/QButton
1 2 3 4 5 6 7 8 | <com.manojbhadane.QButton android:layout_width="match_parent" android:layout_height="wrap_content" android:text="OK" app:qb_backgroundColor="@color/green" app:qb_radius="100" app:qb_strokeColor="@color/darkGreen" app:qb_strokeWidth="5" /> |
我做一个非常好的按钮样式按钮的方式是子类Button对象并应用颜色过滤器。这也通过对按钮应用alpha来处理启用和禁用状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | import android.annotation.TargetApi; import android.content.Context; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LightingColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Build; import android.util.AttributeSet; import android.widget.Button; public class DimmableButton extends Button { public DimmableButton(Context context) { super(context); } public DimmableButton(Context context, AttributeSet attrs) { super(context, attrs); } public DimmableButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @SuppressWarnings("deprecation") @Override public void setBackgroundDrawable(Drawable d) { // Replace the original background drawable (e.g. image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackgroundDrawable(layer); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void setBackground(Drawable d) { // Replace the original background drawable (e.g. image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackground(layer); } /** * The stateful LayerDrawable used by this button. */ protected class DimmableButtonBackgroundDrawable extends LayerDrawable { // The color filter to apply when the button is pressed protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1); // Alpha value when the button is disabled protected int _disabledAlpha = 100; // Alpha value when the button is enabled protected int _fullAlpha = 255; public DimmableButtonBackgroundDrawable(Drawable d) { super(new Drawable[] { d }); } @Override protected boolean onStateChange(int[] states) { boolean enabled = false; boolean pressed = false; for (int state : states) { if (state == android.R.attr.state_enabled) enabled = true; else if (state == android.R.attr.state_pressed) pressed = true; } mutate(); if (enabled && pressed) { setColorFilter(_pressedFilter); } else if (!enabled) { setColorFilter(null); setAlpha(_disabledAlpha); } else { setColorFilter(null); setAlpha(_fullAlpha); } invalidateSelf(); return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } } |
值 styles.xml
1 2 3 4 5 6 7 8 9 | <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="RedAccentButton" parent="ThemeOverlay.AppCompat.Light"> <item name="colorAccent">#ff0000</item> </style> |
然后:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <Button style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="text" /> <Button style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="false" android:text="text" /> <Button style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="text" android:theme="@style/RedAccentButton" /> <Button style="@style/Widget.AppCompat.Button.Colored" android:layout_width="match_parent" android:layout_height="wrap_content" android:enabled="false" android:text="text" android:theme="@style/RedAccentButton" /> |
根据材料设计指南,您需要使用类似的样式
下面的代码
1 2 3 4 | <style name="MyButton" parent="Theme.AppCompat.Light> <item name="colorControlHighlight">#F36F21</item> <item name="colorControlHighlight">#FF8D00</item> </style> |
并在布局中将此属性添加到您的按钮
1 | android:theme="@style/MyButton" |