当我们第一次看到这种图标是,第一反映就是这怎么绘制啊?赶紧要UI小姐姐切个图算了,但是除了切图,其实我们还可以通过代码的方式完全绘制出来,下面我们就来分析一下,具体怎么绘制?
如上图所示,这个图标其实就是分为三个部分,红色,黄色,绿色,并且三个部分都是一样的,现在我们想想,我们只需要绘制完成一个部分,然后再把这个部分旋转一定的角度,改变它的颜色,是不是就能绘制出其它两个部分了?答案肯定是可以的,至于中间的两个圆,那就十分的简单了。
那么我们如何绘制其中的一个部分了,就拿 红色 部分来说, canvas 中的API也不能直接绘制出来啊,既然不能直接绘制出来,那我们就把它拆分,一点一点的绘制不就行了。
图中AB是一个圆弧 BC是一条直线,CD又是一个圆弧,DA又是一条直线,那么我们把它们都绘制出来,用 Path.lineTo(),方法连接起来不就行了吗?
看图可知,x1和x2这两条线是平行的,至于为什么平行了?你拿着谷歌的原图画一条直线比较一下就知道了,D点B点C点是在一条直线上的,x2又是过圆心的直线 由于3个部分组成了一个圆,那么每个部分的弧度都是120度,即DC扫过的弧度为120度,那么由图可知 DOC 的度数为120,那么 DOB 和 COB 的度数都是60度,那么由此可以确定,OCB度数为30度,AOE度数为30度
图中 OB是我们自己定义小圆的半径,OB长度知道,OC是自己定义的大圆半径,OC长度知道,那么根据图中线段与角度的关系
A,B,C,D这几点的坐标用三角函数可以求出来
求出C点坐标
c点横坐标 BC=center_x+OB/tant30
c点的纵坐标 就等于OB 为 center_y-100
求出A点坐标
a点的横坐标 OE=center_x-cos30*100
a点的纵坐标 AE=center_y+sin30*100
到此我们所需要的坐标就都求出来了
先画AB这段圆弧,要画圆弧,就要知道AB这段的弧度 AOE+EOD+DOB=120度,是可以明确求出的,所以AB的弧度为120度,
由于画圆弧 需要四个参数 RectF 圆弧的范围(大小),startAngle开始点的弧度,sweepAngle扫过的弧度,Paint 画笔
public void drawArc(@RecentlyNonNull RectF oval, float startAngle, float sweepAngle, @RecentlyNonNull Paint paint)
Paint 画笔 我们自己创建
sweepAngle扫过的弧度 我们已经计算出来了 120度
startAngle开始的弧度 就是从A这个点开始,AOZ就是开始绘制时的弧度了 计算可知是 150度
RectF 现在就剩下范围了
RectF 的范围分为两个,图中小的矩形和大的矩形 ,小矩形画AB圆弧这段,大矩形画CD圆弧这段
我们开始定义
小圆的半径 100 即OB=100
大圆半径 200吧 即 OG=200;
定义圆心坐标 o center_x,center_y
RectF rect_inner 小圆矩形框
RectF rect_outer 大圆矩形框
在onMeasure方法中获取控件的 宽 ,高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
}
圆心坐标 center_x=width/2 center_y=height /2
//小圆矩形框 设置
RectF rect_inner=new RectF(center_x-100,center_y-100,center_x+100,center_y+100)
//大圆矩形框设置
RectF rect_outer =new RectF(center_x-200,center_y-200,center_x+200,center_y+200)
public class ViewCircle extends View
{
private Paint mPaint;
private Context context;
//控件宽高
private int width, height;
//圆心坐标
private int centerX, centerY;
//小圆半径
private int smallRadius = 100;
//大圆半径
private int largeRadius = 200;
//小圆的范围
private RectF rectInner;
//大圆的范围
private RectF rectOuter;
public ViewCircle(Context context)
{
super(context);
init(context);
}
public ViewCircle(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context);
}
public ViewCircle(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context)
{
this.context = context;
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(context.getResources().getColor(R.color.colorBlack));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
centerX = width / 2;
centerY = height / 2;
rectInner = new RectF(centerX - smallRadius, centerY - smallRadius, centerX + smallRadius, centerY + smallRadius);
rectOuter =new RectF(centerX-largeRadius,centerY-largeRadius,centerX+largeRadius,centerY+largeRadius);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas1 = new Canvas(bitmap);
Path path = new Path();
//画小圆的圆弧
path.addArc(rectInner, 150, 120);
//链接到c点
//c点横坐标 BC=centerX+OB/tant30
//c点的纵坐标 就等于OB 为 100
//Math 里面的 sin cos tan 是弧度制,不能直接写30度,需要把角度转为弧度 Math.PI*30.0/180.0
float cx= centerX+(float) (smallRadius / Math.tan(Math.PI*30.0/180.0));
float cy=centerY-smallRadius;
//画直线
path.lineTo(cx,cy);
//画大圆圆弧 根据图可知 大圆的圆弧 开始角度为 -30度 逆时针 扫过-120度
path.addArc(rectOuter, -30, -120);
//画链接到A点的直线 求出A点的坐标
float ax=centerX-(float) (smallRadius * Math.cos(Math.PI*30.0/180.0));
float ay=centerY+(float) (smallRadius * Math.sin(Math.PI*30.0/180.0));
path.lineTo(ax,ay);
canvas1.drawPath(path, mPaint);
canvas.drawBitmap(bitmap, 0, 0, mPaint);
}
}
//以圆心旋转120度
Matrix matrix=new Matrix();
matrix.setRotate(120,centerX,centerX);
path.transform(matrix);
canvas1.drawPath(path, mPaint);
//再次旋转
path.transform(matrix);
canvas1.drawPath(path, mPaint);
//设置画笔颜色为红色
mPaint.setColor(color[0]);
canvas1.drawPath(path, mPaint);
//以圆心旋转120度
Matrix matrix=new Matrix();
matrix.setRotate(120,centerX,centerX);
path.transform(matrix);
mPaint.setColor(color[1]);
canvas1.drawPath(path, mPaint);
//再次旋转
path.transform(matrix);
mPaint.setColor(color[2]);
canvas1.drawPath(path, mPaint);
//绘制中间的小圆
mPaint.setColor(color[4]);
canvas1.drawCircle(centerX,centerY,smallRadius,mPaint);
//绘制蓝色小圆
mPaint.setColor(color[3]);
canvas1.drawCircle(centerX,centerY,smallRadius-10,mPaint);
canvas.drawBitmap(bitmap, 0, 0, mPaint);
@Override
public boolean onTouchEvent(MotionEvent event)
{
int action=event.getAction();
//
if (action!=MotionEvent.ACTION_DOWN && action!=MotionEvent.ACTION_UP)
{
return super.onTouchEvent(event);
}
float x = event.getX();
float y = event.getY();
int pixe=bitmap.getPixel((int)x,(int)y);
//取到的颜色值是透明的
if(Color.TRANSPARENT==pixe)
{
return false;
}else
{
for (int i=0;i