话题来源:最近接触个新项目,需要在项目中加个圆角按钮。美工只给了个效果图和颜色值标记,按照以前的经验创建三个xml文件,一个定义selector标签选择器,另外两个用shape标签来定义按钮正常和点击状态。写过之后同事说项目中定义过这个样式,文件太多没找到,只有使用这三个xml文件来定义这个Button的样式。
功能做好后,思考了一下,创建三个xml文件来修饰一个Button太大动干戈了,项目中xml文件将会冗余难管理。可不可以自定义一个Button控件,我们只需要在xml中指定Button的圆角半径和颜色就可以定义一个按钮呢?
使用方式:
1、把自定义按钮的java类AA_Button_Circle.java复制到自己的java包中,再将styleable_aa_button_circle.xml复制到values文件夹中。
2、在用到这个按钮的布局文件中添加<你的包名.AA_Button_Circle xmlns:myapp="http://schemas.android.com/apk/res-auto" myapp:aa_bg_color="颜色" myapp:aa_corner_radius="圆角半径dp"/>,自己指定控件的宽高等属性
实现原理:
1、安卓的selector可以在代码中用StateListDrawable实现。
2、shap可以在代码中用GradientDrawable来实现;
3、安卓通过declare-styleable标签给自定义控件添加自定义属性;
4、在使用自定义标签时要使用xmlns:myapp="http://schemas.android.com/apk/res-auto",其中xmlns:myapp中的myapp只是个标记,自己可以改成任意字母组合
实现代码:
AA_Button_Circle.java
/**
* 定义控件属性的文件styleable_aa_button_circle.xml
*
* xml中使用时先加入xmlns:myapp="http://schemas.android.com/apk/res-auto" ,再定义属性如:
* myapp:aa_bg_color="#f39800" myapp:aa_corner_radius="5dp"
*
* @author Administrator
*
*/
public class AA_Button_Circleextends Button {
public AA_Button_Circle(Contextcontext) {
super(context);
}
/**
* 如果没有配置按钮颜色使用默认颜色
*/
private static final StringDefaultColor ="#2196F3";
/**
* 如果没有配置圆角半径,使用默认圆角半径
*/
private static final int DefaultRadius = 2;
/**
* 初始化填充颜色,默认值为blue500
*/
private ColorStateList fillColor;
private ColorStateList fillColor_pressed;
@SuppressLint("Recycle")
public AA_Button_Circle(Contextcontext, AttributeSetattrs) {
super(context,attrs);
TypedArray myattrs = context.obtainStyledAttributes(attrs, R.styleable.aa_button_circle, 0, 0);
// 获取圆角半径
float cornerRadius =myattrs.getDimensionPixelSize(R.styleable.aa_button_circle_aa_corner_radius,
DefaultRadius);
// 获取填充颜色
fillColor = myattrs.getColorStateList(R.styleable.aa_button_circle_aa_bg_color);
if (fillColor ==null) {
fillColor = ColorStateList.valueOf(Color.parseColor(DefaultColor));
}
// 获取点击后颜色,默认是按钮颜色的一半透明度
fillColor_pressed = myattrs.getColorStateList(R.styleable.aa_button_circle_aa_pressed_bg_color);
if (fillColor_pressed ==null) {
// 通过修改透明度产生点击效果
// fillColor_pressed =
// ColorStateList.valueOf(changeAlpha(fillColor.getDefaultColor(),
// 127));
// 添加白色占比
fillColor_pressed = ColorStateList.valueOf(add_White(fillColor.getDefaultColor(), 30));
// 通过修改亮度产生点击效果
// fillColor_pressed =
// ColorStateList.valueOf(change_White_Black(fillColor.getDefaultColor(),
// -20));
}
int fillColor1 =fillColor.getDefaultColor();// 内部填充颜色
GradientDrawable gd1 = new GradientDrawable();// 创建drawable
gd1.setColor(fillColor1);
gd1.setCornerRadius(cornerRadius);
GradientDrawable gd2 = new GradientDrawable();// 创建drawable
gd2.setColor(fillColor_pressed.getDefaultColor());
gd2.setCornerRadius(cornerRadius);
// 定义选择器
StateListDrawable selector = new StateListDrawable();
selector.addState(new int[] { -android.R.attr.state_pressed },gd1);
selector.addState(new int[] { android.R.attr.state_pressed },gd2);
this.setBackgroundDrawable(selector);
this.setTextColor(Color.WHITE);
}
/**
* 修改颜色透明度
*
* @param color
* @param alpha
* @return
*/
public int changeAlpha(int color,int alpha) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha,red,green, blue);
}
/**
* 修改亮度
*
* @param color
* @param percent,正数为变亮,负数为变暗
* @return
*/
public int change_White_Black(int color,int percent) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
red = red * (100 + percent) / 100;
green = green * (100 + percent) / 100;
blue = blue * (100 + percent) / 100;
red = (red < 255) ?red : 255;
green = (green < 255) ?green : 255;
blue = (blue < 255) ?blue : 255;
return Color.argb(Color.alpha(color),red,green, blue);
}
/**
* 合成白色
*
* @param color
* @param percent,0-100占比
* @return
*/
public int add_White(int color,int percent) {
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
red = (red * (100 -percent) + 255 *percent) / 100;
green = (green * (100 -percent) + 255 *percent) / 100;
blue = (blue * (100 -percent) + 255 *percent) / 100;
red = (red < 255) ?red : 255;
green = (green < 255) ?green : 255;
blue = (blue < 255) ?blue : 255;
return Color.argb(Color.alpha(color),red,green, blue);
}
styleable_aa_button_circle.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="aa_button_circle">
<attr name="aa_corner_radius" format="dimension" />
<attr name="aa_bg_color" format="color" />
<attr name="aa_pressed_bg_color" format="color" />
</declare-styleable>
</resources>