先看效果图:
分析这是线性渐变色,圆弧半径刚好是高度的一半,文字居中处理,大小,颜色可调
首先开始自定义控件的基本步骤
1、style自定义属性
<!--自定义控件属性-->
<declare-styleable name="MyGradientRoundButton">
<attr name="colorStart" format="reference" />
<attr name="colorEnd" format="reference" />
<attr name="round" format="dimension" />
<attr name="clickEffect" format="boolean" />
<attr name="colorPressStart" format="reference" />
<attr name="colorPressEnd" format="reference" />
<attr name="btnText" format="reference" />
<attr name="btnTextSize" format="dimension" />
<attr name="btnTextColor" format="reference" />
</declare-styleable>
注:原本我是想还有点击效果的
2、继承view核心代码
public class MyGradientRoundButton extends View {
private int colorStart;
private int colorEnd;
private int colorPressStart;
private int colorPressEnd;
private int colorS;
private int colorE;
private String text;
private int textColor;
private float textSize;
private float round;
private boolean clickEffect;
private RectF mBackGroundRect;
private LinearGradient backGradient;
//默认画笔
private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Paint mPaintText = new Paint();
public MyGradientRoundButton(Context context, AttributeSet attrs) {
super(context, attrs);
//获取自定义属性
if (attrs != null) {
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyGradientRoundButton);
colorStart = typedArray.getColor(R.styleable.MyGradientRoundButton_colorStart, getResources().getColor(R.color.btn_color_start));
colorEnd = typedArray.getColor(R.styleable.MyGradientRoundButton_colorEnd, getResources().getColor(R.color.btn_color_end));
round = typedArray.getDimension(R.styleable.MyGradientRoundButton_round, Utils.dip2px(context, 10));
clickEffect = typedArray.getBoolean(R.styleable.MyGradientRoundButton_clickEffect, false);
colorPressStart = typedArray.getColor(R.styleable.MyGradientRoundButton_colorPressStart, getResources().getColor(R.color.btn_color_PStart));
colorPressEnd = typedArray.getColor(R.styleable.MyGradientRoundButton_colorPressEnd, getResources().getColor(R.color.btn_color_PEnd));
text = typedArray.getString(R.styleable.MyGradientRoundButton_btnText);
textColor = typedArray.getColor(R.styleable.MyGradientRoundButton_btnTextColor, getResources().getColor(R.color.black));
textSize = typedArray.getDimension(R.styleable.MyGradientRoundButton_btnTextSize, 16);
colorS = colorStart;
colorE = colorEnd;
typedArray.recycle();
}
//必须加,否则onTouchEvent只响应ACTION_DOWN
setClickable(true);
//设置抗锯齿
mPaint.setAntiAlias(true);
//设置防抖动
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.FILL);
mPaintText.setAntiAlias(true);
mPaintText.setDither(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBackGroundRect = new RectF(0, 0, w, h);
backGradient = new LinearGradient(0, 0, w, 0, new int[]{colorS, colorE}, null, Shader.TileMode.CLAMP);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setShader(backGradient);
//绘制背景 圆角矩形
if (mBackGroundRect != null) {
canvas.drawRoundRect(mBackGroundRect, round, round, mPaint);
}
//绘制文字
mPaintText.setTextSize(textSize);
mPaintText.setColor(textColor);
mPaintText.setTextAlign(Paint.Align.CENTER);
Paint.FontMetricsInt fontMetrics = mPaintText.getFontMetricsInt();
float baseline = mBackGroundRect.top + (mBackGroundRect.bottom - mBackGroundRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
canvas.drawText(text, canvas.getWidth() / 2, baseline, mPaintText);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (clickEffect) {
//刷新
invalidate();
//判断点击操作
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
colorS = colorPressStart;
colorE = colorPressEnd;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
colorS = colorStart;
colorE = colorEnd;
break;
case MotionEvent.ACTION_CANCEL:
break;
}
}
return super.onTouchEvent(event);
}
public void setText(String text) {
if (!TextUtils.isEmpty(text)) {
this.text = text;
invalidate();
}
}}
关键代码讲解:
onDraw():绘制图形过程,canvas.drawXXX()就是在绘制一层层图层,所以drawRoundRect要在drawText之前
LinearGradient:线性渐变色
RectF:正方形,配合drawRoundRect就可以画出带圆角的图形
onSizeChanged():发生在onDraw()之前,一般可以做些不变的参数设定,调用onDraw(),它也不调用的
invalidate():每调一次,也就调用了一次onDraw()方法,这样就可以做点击效果了
3、引用列子
<com.yiban1314.yiyue.widge.MyGradientRoundButton
android:id="@+id/dialog_guide_reg"
android:layout_width="match_parent"
android:layout_height="@dimen/d80px"
app:clickEffect="false"
app:round="@dimen/d40px"
app:colorStart="@color/btn_color_start"
app:colorEnd="@color/btn_color_end"
app:btnText="@string/register"
app:btnTextColor="@color/c_22"
app:btnTextSize="@dimen/s32px"
android:layout_marginBottom="@dimen/d64px"
android:layout_marginTop="@dimen/d64px"/>
这个自定义控件有个缺陷宽高不能用wrap_content属性。