欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

一个仪表盘自定义控件

程序员文章站 2022-06-08 16:26:36
...

 最近开发中设计给出了一个类似于仪表盘的控件,虽然可以用多张图代替,但是还是写了一个类似的自定义控件,成果如下图:

一个仪表盘自定义控件

1、首先把原点设置在圆心

    //把方框平移到正中间
        canvas.translate(dx, dy);
        canvas.save();
        canvasR = Math.min(getWidth(), getHeight()) / 2;
        markWidth = canvasR / 20;
        tableWidth = canvasR / 10;
        mPaint.setStyle(Paint.Style.STROKE);

2、从外围开始描绘控件

 //填写文字刻度
        mPaint.setTextSize(outTextSize);
        int count = 0;
        while (count < mMaxCount) {
            //填写外围文字
            Rect bounds = new Rect();
            String text = 100 / (mMaxCount - 1) * count + "";
            mPaint.getTextBounds(text, 0, text.length(), bounds);
            float offSet = (bounds.bottom - bounds.top);
            //角度
            float angle = startAngle + sweepAngle / (mMaxCount - 1) * count;

            textWidth = offSet + 3;//3间距显得好看点
            //半径
            float r = canvasR - textWidth;
            canvas.rotate(90 + angle, getmX(r, angle), getmY(r, angle));
            canvas.drawText(text, getmX(r, angle), getmY(r, angle), mPaint);
            canvas.rotate(-90 - angle, getmX(r, angle), getmY(r, angle));

            //填写大刻度
            canvas.drawLine(getmX(r - 3, angle), getmY(r - 3, angle), getmX(r - markWidth, angle), getmY(r - markWidth, angle), mPaint);
            int count0 = 1;

            //填写小刻度
            while (count > 0 && count0 < mMinCount) {
                //角度
                float angle0 = angle - sweepAngle / (mMaxCount - 1) + sweepAngle / (mMaxCount - 1) * count0 / mMinCount;
                canvas.drawLine(getmX(r - markWidth / 2, angle0), getmY(r - markWidth / 2, angle0), getmX(r - markWidth, angle0), getmY(r - markWidth, angle0), mPaint);
                count0++;
            }

            count++;
        }

        //刻度下面弧线
        float markR = canvasR - textWidth - markWidth;
        RectF markRectf = new RectF(-markR, -markR, markR, markR);
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawArc(markRectf, startAngle, sweepAngle, false, mPaint);

        float tableR = markR - canvasR / 40 - tableWidth / 2;
        RectF mTableRectF = new RectF(-tableR, -tableR, tableR, tableR);
        //进度条底部
        Path tablePath = new Path();
        tablePath.addArc(mTableRectF, startAngle - 90, sweepAngle);
        //计算路径的长度
        PathMeasure pathMeasure = new PathMeasure(tablePath, false);
        float length = pathMeasure.getLength();
        float step = length / 21;
        DashPathEffect dashPathEffect = new DashPathEffect(new float[]{step * 9 / 10, step / 10}, 0);
        mPaint.setPathEffect(dashPathEffect);
        mPaint.setStrokeWidth(tableWidth);
        canvas.rotate(90);
        canvas.drawPath(tablePath, mPaint);
        canvas.rotate(-90);

        //进度条
        Path progressPath = new Path();
        progressPath.addArc(mTableRectF, startAngle - 90, sweepAngle * progress / 100);
        SweepGradient mColorShader = new SweepGradient(0, 0, SWEEP_GRADIENT_COLORS, null);
        mPaint.setShader(mColorShader);
        canvas.rotate(90);
        canvas.drawPath(progressPath, mPaint);
        canvas.rotate(-90);


        //画带阴影的圆
        float circleR = tableR - canvasR / 40 - tableWidth / 2;
        initPaint();
        canvas.drawCircle(-canvasR / 160, canvasR / 160, circleR, mPaint);
        mPaint.setColor(Color.WHITE);
        canvas.drawCircle(0, 0, circleR, mPaint);
        mPaint.setColor(Color.parseColor("#cccccc"));
        mPaint.setStyle(Paint.Style.STROKE);
        canvas.drawCircle(0, 0, circleR, mPaint);

        //画内圆
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(Color.parseColor("#fafafa"));
        canvas.drawCircle(0, 0, circleR * 2 / 5, mPaint);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.parseColor("#dddddd"));
        canvas.drawCircle(0, 0, circleR * 2 / 5, mPaint);

        //画进度小圆点
        mPaint.setColor(Color.parseColor("#FF6610"));
        mPaint.setStyle(Paint.Style.FILL);
        canvas.drawCircle(getmX(circleR - canvasR / 20, startAngle + sweepAngle * progress / 100)
                , getmY(circleR - canvasR / 20, startAngle + sweepAngle * progress / 100), canvasR / 40, mPaint);

        //画中间字符
        Rect bounds = new Rect();
        String text = progress + "%";
        mPaint.setTextSize(proTextSize);
        mPaint.getTextBounds(text, 0, text.length(), bounds);
        float offSet = (bounds.bottom - bounds.top);
        Rect bounds2 = new Rect();
        String text2 = decText;
        mPaint.setTextSize(decTextSize);
        mPaint.setColor(Color.parseColor("#cccccc"));
        mPaint.getTextBounds(text, 0, text.length(), bounds2);
        float offSet2 = (bounds2.bottom - bounds2.top);
        canvas.drawText(text2, 0, (offSet2 + offSet + 3) / 2, mPaint);
        mPaint.setColor(Color.parseColor("#FF6610"));
        mPaint.setTextSize(proTextSize);
        canvas.drawText(text, 0, (offSet2 + offSet + 3) / 2 - offSet2 - 3, mPaint);

求x,y坐标方法

  private float getmX(float r, float angle) {
        return (float) Math.cos(angle * Math.PI / 180) * r;
    }

    private float getmY(float r, float angle) {
        return (float) Math.sin(angle * Math.PI / 180) * r;
    }

源码:https://download.csdn.net/download/qq_40667603/11945307