自定义View - 圆型齿轮进度条

1,068 阅读2分钟

效果图

image.png


1.设置正方形自定义View

//控件整体宽高
private int viewWidth, viewHeight;

/**
 * 设置大小
 * 将这个View设置成一个正方形(以宽为标准)
 */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    //获取宽高
    int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    //过滤无效的数值
    if (width == 0 || height == 0) {
        return;
    }
    viewWidth = width;
    viewHeight = viewWidth;
    //设置View的宽高
    setMeasuredDimension(viewWidth, viewHeight);
}

原理解剖

假设我们需要画100个刻度

已知

  • 圆⚪总共 = 360° ----> 分成100份 ----> 360° / 100 = 3.6°
  • 100个角度[0°, 3.6°, 7.2°....,360°]
  • 圆心C点坐标点 ----> ( (viewWidth / 2) , (viewHeight / 2) )
  • 半径r ----> viewWidth / 2 知道上面四个条件我们就可以求100个角度在圆上的100个点坐标,接下来我们求下面A,B两点坐标即可画出一个刻度。
  • 公式求圆上点的坐标_fearlazy-CSDN博客_求圆上一点的坐标 image.png

绘制某一个角度上的刻度线

    @Override
    protected void onDraw(Canvas canvas) {
        //圆心
        float[] centerPoint = {viewWidth / 2f, viewHeight / 2f};
        //半径
        float[] radiusArray = new float[2];
        //大圆的半径
        radiusArray[0] = (viewWidth / 2f) - (progressPaint.getStrokeWidth() / 2f);
        //小圆的半径
        radiusArray[1] = radiusArray[0] - 40;

        drawLine(canvas, progressPaint, centerPoint, 0, radiusArray);
        drawLine(canvas, progressPaint, centerPoint, 90, radiusArray);
        drawLine(canvas, progressPaint, centerPoint, 180, radiusArray);
        drawLine(canvas, progressPaint, centerPoint, 270, radiusArray);
    }

    /**
     * # 绘制某一个角度上的刻度线
     *
     * @param centerPoint 圆心点坐标 [x, y]
     * @param angle       角度
     * @param radiusArray 两个园分别的半径
     */
    private void drawLine(Canvas canvas, Paint paint, float[] centerPoint, float angle, float[] radiusArray) {
        //过滤
        if (centerPoint.length != 2) {
            return;
        }
        //过滤
        if (radiusArray.length != 2) {
            return;
        }
        /**
         * 数学公式
         */

        //A点坐标
        int x1 = (int) (centerPoint[0] + (radiusArray[0] * Math.cos(Math.toRadians(angle))));
        int y1 = (int) (centerPoint[1] + (radiusArray[0] * Math.sin(Math.toRadians(angle))));
        //B点坐标
        int x2 = (int) (centerPoint[0] + (radiusArray[1] * Math.cos(Math.toRadians(angle))));
        int y2 = (int) (centerPoint[1] + (radiusArray[1] * Math.sin(Math.toRadians(angle))));
        //打印信息
        Log.e("liu1220", "drawLine    angle    " + angle + "    radiusArray = " + radiusArray[0] + "," + radiusArray[1] + "    x1 = " + x1 + "    y1 = " + y1 + "    x2 = " + x2 + "    y2 = " + y2);
        //绘制直线
        canvas.drawLine(x1, y1, x2, y2, paint);
    }

效果如下:

1b68afb4062942852d03dc0289dfc49.jpg