效果
自己动手写了一个自定义圆盘,效果如下:
思路
一些颜色,字体细节没有调,自定义属性也没有加上去,这些都比较简单!说下思路吧:
这个控件看起来比较复杂,其实经过分解也很简单,这些东西都是通过canvas,paint画出来的,麻烦一点的是计算坐标.下面是几个注意点:
1.使用getWidth()时需要测量onMeasure.
2.Paint创建的事件不要在onDraw.
3.画刻度的时候,可以通过正余玄来计算,但是比较麻烦,我通过旋转坐标系来实现的,坐标系旋转之后要记得旋转回来.
代码
下面是所有代码
public class PanView extends View {
private int mWidth;
private int mHeight;
private int innerCircleWidth1 = 10;
private int innerCircleWidth2 = 4;
private int innerLineWidth = 8;
private int outerCircleWidth1 = 2;
private int outerCircleWidth2 = 80;
private int mFirstColor = Color.BLUE;
private int mSecondColor = Color.WHITE;
private Paint mPaint;
private Paint mTextPaint;
private int mPercent = 0;
// 里面圆的半径
private int innerReduis1 = 15;
private int innerReduis2 = 35;
private String mText = "";
public PanView(Context context) {
this(context, null);
}
public PanView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(mFirstColor);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mTextPaint = new Paint();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
mWidth = width;
} else {
mWidth = 400;
}
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = height;
} else {
mHeight = 400;
}
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onDraw(Canvas canvas) {
// 确定圆心
int circleX = mWidth / 2;
int circleY = mHeight / 2;
Log.d("ch", circleX + "");
Log.d("ch", circleY + "");
// 画里面的园
drawInnerCircle(canvas, circleX, circleY);
// 画线
drawIndicator(canvas, circleX, circleY, innerReduis1);
// 画最外面的圆弧
drawouterArc1(canvas, circleX, circleY);
// 画内侧的圆弧
drawOuterArc2(canvas, circleX, circleY);
//画正方形
drawRect(canvas, circleX, circleY);
// 画文字
drawText(canvas, circleX, circleY);
}
private void drawText(Canvas canvas, int circleX, int circleY) {
mTextPaint.setTextSize(30);
mTextPaint.setColor(Color.RED);
mText = "已完成";
float textLength = mTextPaint.measureText(mText);
canvas.drawText(mText, (circleX - textLength / 2), circleY + 250, mTextPaint);
}
private void drawRect(Canvas canvas, int circleX, int circleY) {
mPaint.setStrokeWidth(20);
mPaint.setColor(Color.BLUE);
float left = circleX - 20;
float top = circleY + 170;
float right = circleX + 20;
float bottom = top + 20;
canvas.drawRect(left, top, right, bottom, mPaint);
}
private void drawOuterArc2(Canvas canvas, int circleX, int circleY) {
int outerReduis2 = 200;
int left = circleX - outerReduis2;
int top = circleY - outerReduis2;
int right = circleX + outerReduis2;
int bottom = circleY + outerReduis2;
RectF oval = new RectF(left, top, right, bottom);
float startAngle = 45;
float sweepAngle = -270;
mPaint.setColor(Color.GRAY);
mPaint.setStrokeWidth(outerCircleWidth2);
canvas.drawArc(oval, startAngle, sweepAngle, false, mPaint);
float degree = (sweepAngle / 100f) * mPercent;
mPaint.setColor(Color.GREEN);
canvas.drawArc(oval, startAngle + 90, -degree, false, mPaint);
}
private void drawouterArc1(Canvas canvas, int circleX, int circleY) {
int outerReduis1 = 300;
int left = circleX - outerReduis1;
int top = circleY - outerReduis1;
int right = circleX + outerReduis1;
int bottom = circleY + outerReduis1;
RectF oval = new RectF(left, top, right, bottom);
float startAngle = 31;
float sweepAngle = -242;
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(outerCircleWidth1);
canvas.drawArc(oval, startAngle, sweepAngle, false, mPaint);
//画外侧的间隔线
int lineLength = 25;
int count = 9;
float degree = 24.2f;
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(outerCircleWidth1);
canvas.drawLine(circleX, top, circleX, top + lineLength, mPaint);
for (int i = 0; i < 5; i++) {
canvas.rotate(degree, circleX, circleY);
canvas.drawLine(circleX, top, circleX, top + lineLength, mPaint);
}
canvas.rotate(-121, circleX, circleY);
for (int i = 0; i < 5; i++) {
canvas.rotate(-degree, circleX, circleY);
canvas.drawLine(circleX, top, circleX, top + lineLength, mPaint);
}
canvas.rotate(121, circleX, circleY);
}
private void drawInnerCircle(Canvas canvas, int circleX, int circleY) {
int left = circleX - innerReduis2;
int top = circleX - innerReduis2;
int right = circleX + innerReduis2;
int bottom = circleX + innerReduis2;
Rect rect = new Rect(left, top, right, bottom);
mPaint.setStrokeWidth(innerCircleWidth2);
canvas.drawCircle(circleX, circleY, innerReduis2, mPaint);
mPaint.setStrokeWidth(innerCircleWidth1);
canvas.drawCircle(circleX, circleY, innerReduis1, mPaint);
}
private void drawIndicator(Canvas canvas, int circleX, int circleY, int innerReduis1) {
float startX = circleX;
float startY = circleY - innerCircleWidth1 / 2;
float stopX = circleX;
float stopY = circleY - 200;
mPaint.setStrokeWidth(innerLineWidth);
mPaint.setColor(Color.YELLOW);
float degree = (float) (1.21 * mPercent) * 2 - 121;
canvas.rotate(degree, circleX, circleX);
canvas.drawLine(startX, startY, stopX, stopY, mPaint);
canvas.rotate(-degree, circleX, circleX);
}
public void setPersent(int persent) {
mPercent = persent;
invalidate();
}
}