自定义控件流程:
1.在attr中添加自定义属性
2.在xml中设置属性
3.写一个自定义属性的类在构造方法中获得xml设置的属性
4.重写onmeassure 和onDraw方法
代码:
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.example.administrator.yihaodai.R;
/**
* Created by Administrator on 2017/3/26.
*/
public class CustomXinyongView extends View {
//半径
private int bigCircleRadio;
private int smallDashRadio;
private int scoreRadio;
//线宽
private int bigCircleStrokeWidth;
private int smallDashStrokeWidth;
private int scorePointWidth;
//颜色
private int bigCircleColor;
private int bigCirecleBackColor;
private int scorePointColor;
private int smallDashColor;
//字体大小
private int titleSize;
private int detailSize;
//字符串
private String mtitle = "50";
private String detail = "信用中等";
//分数
private int mScore;
//圆心位置
private int cx;
private int cy;
public CustomXinyongView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomXinyongView, 0, 0);
//获取颜色
bigCirecleBackColor = typedArray.getColor(R.styleable.CustomXinyongView_big_circle_back_color, 0xffffaa00);
bigCircleColor = typedArray.getColor(R.styleable.CustomXinyongView_big_circle_color, 0xffff6600);
scorePointColor = typedArray.getColor(R.styleable.CustomXinyongView_score_point_color, 0xffff6600);
smallDashColor = typedArray.getColor(R.styleable.CustomXinyongView_small_dash_color, 0xffffaa00);
//获取半径 用dimension好像会变形
bigCircleRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_big_circle_radio, 200);
smallDashRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_small_dash_radio, 120);
scoreRadio = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_socre_point_radio, 90);
//获取线宽
bigCircleStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_big_circle_stroke_width, 10);
smallDashStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_small_dash_stroke_width, 10);
scorePointWidth = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_score_point_stroke_width, 3);
//分数
mScore = typedArray.getInteger(R.styleable.CustomXinyongView_mScore, 50);
//获取字体大小
titleSize = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_titleSize, 60);
detailSize = typedArray.getDimensionPixelSize(R.styleable.CustomXinyongView_detailSize, 30);
//获取字符串
mtitle = String.valueOf(mScore);
detail = typedArray.getString(R.styleable.CustomXinyongView_detail_text);
//圆心位置
cx = bigCircleRadio + getPaddingLeft();
cy = bigCircleRadio + getPaddingTop();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//
if (widthMode == MeasureSpec.EXACTLY) {
width = widthSize;
cx = width / 2;
} else {
width = 2 * cx;
}
if (heightMode == MeasureSpec.EXACTLY) {
height = heightSize;
} else {
height = 2 * cy;
}
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//虚线小圆
initDashCircle(canvas, smallDashColor, smallDashRadio);
//大圆背景
initScoreCircle(canvas, 100, bigCirecleBackColor, bigCircleRadio);
//分数盘
initScoreCircle(canvas, mScore, bigCircleColor, bigCircleRadio);
//指针
initScorePoint(canvas, mScore, scorePointColor);
initTitleText(canvas);
initScore(canvas);
}
/**
* 画小圆虚线
*
* @param canvas
* @param color
* @param smallDashRadio
*/
private void initDashCircle(Canvas canvas, int color, int smallDashRadio) {
//画笔
Paint paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);//抗锯齿
paint.setStrokeWidth(smallDashStrokeWidth);//设置线宽
paint.setStyle(Paint.Style.STROKE);//设置空心
float pointLength = (float) (2 * Math.PI * smallDashRadio * 2 / 3 / 205);//设置分割线
paint.setPathEffect(new DashPathEffect(new float[]{pointLength, pointLength * 11, pointLength, pointLength * 11}, 0));
//位置和大小
RectF rectF = new RectF(cx - smallDashRadio, cy - smallDashRadio, cx + smallDashRadio, cy + smallDashRadio);//半径100,圆心200.200
//画弧线
canvas.drawArc(rectF, 150, 240, false, paint);
}
/**
* 画指针
*
* @param canvas
* @param score
* @param color
*/
private void initScorePoint(Canvas canvas, int score, int color) {
if (score <= 0) {
score = 1;
}
//1.绘制圆
Paint paint = new Paint();
int paintWidth = scorePointWidth;
//画笔
paint.setColor(color);
paint.setAntiAlias(true);//抗锯齿
paint.setStrokeWidth(paintWidth);//设置线宽
paint.setStyle(Paint.Style.FILL_AND_STROKE);//设置实心
//画圆
float cx1 = (float) (cx + scoreRadio * Math.cos(Math.toRadians(210 - score * 240 / 100)));
float cy1 = (float) (cy - scoreRadio * Math.sin(Math.toRadians(210 - score * 240 / 100)));
float circlePointRadio = paintWidth * 2;
canvas.drawCircle(cx1, cy1, circlePointRadio, paint);
//2.绘制三角形
//A点坐标
float pointAx = (float) (cx + (scoreRadio + 2 * paintWidth * 2) * Math.cos(Math.toRadians(210 - score * 240 / 100)));
float pointAy = (float) (cy - (scoreRadio + 2 * paintWidth * 2) * Math.sin(Math.toRadians(210 - score * 240 / 100)));
//获得B和C点的坐标
//b和c点到圆心的距离
float lBC1 = (float) (Math.sqrt(3) / 2 * circlePointRadio);//短边
float lBC2 = (scoreRadio + circlePointRadio / 2);//长边
float lBC = (float) Math.sqrt(Math.pow(lBC1, 2) + Math.pow(lBC2, 2));//斜边
//B点的角度和坐标
double aphaB = Math.toRadians(210 - score * 240 / 100) - Math.asin(lBC1 / lBC);
float pointBx = (float) (cx + (lBC) * Math.cos(aphaB));
float pointBy = (float) (cy - (lBC) * Math.sin(aphaB));
//C点的角度和坐标
double aphaC = Math.toRadians(210 - score * 240 / 100) + Math.asin(lBC1 / lBC);
float pointCx = (float) (cx + (lBC) * Math.cos(aphaC));
float pointCy = (float) (cy - (lBC) * Math.sin(aphaC));
Path path = new Path();
path.moveTo(pointAx, pointAy);// 此点为多边形的起点
path.lineTo(pointBx, pointBy);
path.lineTo(pointCx, pointCy);
path.close(); // 使这些点构成封闭的多边形
canvas.drawPath(path, paint);
//空心
paint.setStyle(Paint.Style.FILL);//设置实心
paint.setColor(Color.WHITE);
canvas.drawCircle(cx1, cy1, circlePointRadio / 2, paint);
}
/**
* 画大圆(背景/分数线)
*
* @param canvas
* @param score
* @param color
* @param bigCircleRadio
*/
private void initScoreCircle(Canvas canvas, int score, int color, int bigCircleRadio) {
if (score == 0) {
score = 1;
}
int paintWide = bigCircleStrokeWidth;
//画笔
Paint paint = new Paint();
paint.setColor(color);
paint.setAntiAlias(true);//抗锯齿
paint.setStrokeWidth(paintWide);//设置线宽
paint.setStyle(Paint.Style.STROKE);//设置空心
//位置和大小
RectF rectF = new RectF(cx - bigCircleRadio, cy - bigCircleRadio, cx + bigCircleRadio, cy + bigCircleRadio);
//画弧线
canvas.drawArc(rectF, 150, score * 240 / 100, false, paint);
//画圆
float cx1 = (float) (cx + bigCircleRadio * Math.cos(Math.toRadians(210)));
float cy1 = (float) (cy - bigCircleRadio * Math.sin(Math.toRadians(210)));
float cx2 = (float) (cx + bigCircleRadio * Math.cos(Math.toRadians(210 - score * 240 / 100)));
float cy2 = (float) (cy - bigCircleRadio * Math.sin(Math.toRadians(210 - score * 240 / 100)));
paint.setStrokeWidth(paintWide / 2);
canvas.drawCircle(cx1, cy1, paintWide / 4, paint);
canvas.drawCircle(cx2, cy2, paintWide / 4, paint);
}
/**
* 初始化Title
*
* @param canvas
*/
private void initTitleText(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(bigCircleColor);
paint.setTextSize(titleSize);//设置字体大小
paint.setAntiAlias(true);//抗锯齿
Rect bound = new Rect();
paint.getTextBounds(mtitle, 0, mtitle.length(), bound);
int textWidth = bound.width();
canvas.drawText(mtitle, cx - textWidth / 2, cy, paint);
}
/**
* 初始化分数
*
* @param canvas
*/
private void initScore(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(smallDashColor);
paint.setAntiAlias(true);//抗锯齿
paint.setTextSize(detailSize);//设置字体大小
Rect bound = new Rect();
paint.getTextBounds(detail, 0, detail.length(), bound);
int textWidth = bound.width();
canvas.drawText(detail, cx - textWidth / 2, (int) (cy + detailSize * 1.5), paint);
}
public void setScore(int score) {
// TODO: 2017/3/27 设置分数,可以在这里做刷新动画和更改信用评级
mScore = score;
mtitle = String.valueOf(mScore);
postInvalidate();//刷新界面
}
}