我想稍微改变一个标准的Android按钮的颜色,以便更好地匹配客户端的品牌。
到目前为止,我发现最好的方法是将按钮的可绘制对象更改为位于res/drawable/red_button.xml中的可绘制对象:
<?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>
但是这样做需要为我想要自定义的每个按钮创建三个不同的绘图(一个用于静止的按钮,一个用于聚焦时的按钮,一个用于按下时的按钮)。这似乎比我需要的更复杂和非dry。
我真正想做的是对按钮应用某种颜色变换。有没有比我现在做的更简单的方法来改变按钮的颜色?
这是我的解决方案,从API 15开始完美地工作。这个解决方案保留了所有默认的按钮点击效果,如材质涟漪效应。我没有在较低的api上测试它,但它应该可以工作。
你所需要做的就是:
1)创建一个只改变颜色口音的样式:
<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
<item name="colorAccent">@color/com_facebook_blue</item>
</style>
我推荐使用ThemeOverlay。AppCompat或你的主AppTheme作为父,以保留你的其他样式。
2)添加这两行到你的按钮小部件:
style="@style/Widget.AppCompat.Button.Colored"
android:theme="@style/Facebook.Button"
有时你的新颜色口音不会在Android Studio预览中显示,但当你在手机上启动应用程序时,颜色会发生变化。
示例按钮小部件
<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" />
我做一个不同风格的按钮,工作得很好是子类按钮对象,并应用一个颜色过滤器。它还通过对按钮应用alpha来处理启用和禁用状态。
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;
}
}
}