自定义View绘制谷歌 图标

自定义View

  • 自定义控件 绘制谷歌 图标
    • 第一步
    • 第二步
    • 直接上代码,看看绘制出来的第一个部分
    • 再通过旋转,绘制其它两个部分
    • 绘制颜色和中间的小圆
    • 为各个色值添加点击事件

自定义控件 绘制谷歌 图标

自定义View绘制谷歌 图标_第1张图片
当我们第一次看到这种图标是,第一反映就是这怎么绘制啊?赶紧要UI小姐姐切个图算了,但是除了切图,其实我们还可以通过代码的方式完全绘制出来,下面我们就来分析一下,具体怎么绘制?

自定义View绘制谷歌 图标_第2张图片

如上图所示,这个图标其实就是分为三个部分,红色,黄色,绿色,并且三个部分都是一样的,现在我们想想,我们只需要绘制完成一个部分,然后再把这个部分旋转一定的角度,改变它的颜色,是不是就能绘制出其它两个部分了?答案肯定是可以的,至于中间的两个圆,那就十分的简单了。

那么我们如何绘制其中的一个部分了,就拿 红色 部分来说, canvas 中的API也不能直接绘制出来啊,既然不能直接绘制出来,那我们就把它拆分,一点一点的绘制不就行了。
图中AB是一个圆弧 BC是一条直线,CD又是一个圆弧,DA又是一条直线,那么我们把它们都绘制出来,用 Path.lineTo(),方法连接起来不就行了吗?

自定义View绘制谷歌 图标_第3张图片

看图可知,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  现在就剩下范围了

自定义View绘制谷歌 图标_第4张图片
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)

直接上代码,看看绘制出来的第一个部分

自定义View绘制谷歌 图标_第5张图片

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);

自定义View绘制谷歌 图标_第6张图片

绘制颜色和中间的小圆

//设置画笔颜色为红色

    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);

自定义View绘制谷歌 图标_第7张图片

为各个色值添加点击事件

@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

自定义View绘制谷歌 图标_第8张图片

你可能感兴趣的:(View)