您的当前位置:首页正文

温度仪表盘

来源:华佗小知识

效果图如下:


image.png

代码如下,简单实现效果而已,温度改变的回掉接口,自定义文字,颜色等都没暴露对外的方法。可自行修改

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

public class TempertureShow extends View {

    public TempertureShow(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSomeThing();
    }

    private Paint paintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);//中心圆的画笔
    private Paint paintLine = new Paint(Paint.ANTI_ALIAS_FLAG);//线条的画笔
    private Paint paintLineShort = new Paint(Paint.ANTI_ALIAS_FLAG);//间隔线的画笔
    private Paint paintText = new Paint();//起始,结束温度文字的画笔
    private Paint paintTextCenter = new Paint();//中心文字画笔
    private Paint paintTextBottom = new Paint();//底部文字画笔
    private int colorBg = Color.BLUE;
    private int colorFore = Color.RED;
    private int colorText = Color.RED;
    private int colorTextCenter = Color.RED;
    private int colorTextBottom = Color.BLACK;
    private int rCircle;//中心圆的半径
    private int rLine;//线条的半径
    private int rLineShort;//间隔线所在的圆半径
    private RectF ovalCircle = new RectF();//中间的圆
    private RectF oval = new RectF();//圆圈线条
    private RectF ovalLineShort = new RectF();//间隔线的rect,我们是当成一个圆弧画的
    RectF ovalText = new RectF();//起始温度和结束温度,文字弧度所在的rect
    private int intervalAngle;//分成split份的监督
    private int minTemperture = 15;// 最小值
    private int maxTemperTure = 30;// 最大值
    int split = 90;//从135度到405度分成90份
    Path pStart = new Path();//起始温度的文字路径
    Path pEnd = new Path();//结束温度的文字路径
    private int rMax;//最大半径
    private Rect bounds = new Rect();//用来计算中间文字的宽度的
    private double currentAngle = 135;
    Path pathArrow = new Path();//白色的箭头
    private void initSomeThing() {
        paintCircle.setColor(Color.WHITE);
        paintCircle.setStyle(Style.FILL_AND_STROKE);

        paintLine.setColor(colorBg);
        paintLine.setStyle(Style.STROKE);

        paintLineShort.setColor(colorBg);
        paintLineShort.setStrokeWidth(10);
        paintLineShort.setStyle(Style.STROKE);

        paintText.setColor(colorText);
        paintText.setTextSize(22);

        paintTextCenter.setColor(colorTextCenter);
        paintTextCenter.setTextSize(60);
        paintTextCenter.setTextAlign(Align.CENTER);

        paintTextBottom.setColor(colorTextBottom);
        paintTextBottom.setTextAlign(Align.CENTER);
        paintTextBottom.setTextSize(20);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (right != left && top != bottom) {
            int squareL = Math.min(getWidth(), getHeight());
            rMax = squareL / 2;
            rCircle = rMax / 2;// 中间圆的半径
            ovalCircle.set(-rCircle, -rCircle, rCircle, rCircle);
            rLine = rCircle + rCircle / 3;// 蓝线的半径
            rLineShort = rCircle + rCircle * 2 / 3;// 短线的半径
            oval.set(-rLine, -rLine, rLine, rLine);

            intervalAngle = 270 / split;
            ovalLineShort.set(-rLineShort, -rLineShort, rLineShort, rLineShort);
            ovalText.set(-rMax, -rMax, rMax, rMax);
            pStart.reset();
            pEnd.reset();
            pStart.addArc(ovalText, 135 + 20, -20);
            pEnd.addArc(ovalText, 45, -20);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getWidth() / 2, getHeight() / 2);

        // 开始画圆
        canvas.save();
        canvas.rotate((float) (currentAngle - 90));
        pathArrow.addArc(ovalCircle, 90+ 6, 360-12);
        pathArrow.lineTo(0, rCircle + 9);
        pathArrow.close();
        canvas.drawPath(pathArrow, paintCircle);
        canvas.restore();

        canvas.drawArc(oval, 135, 270, false, paintLine);
        paintLineShort.setColor(colorFore);
        for (int i = 0; i <= split; i++) {
            float startAngle = (float) (135 + intervalAngle * i - 0.5);
            if (startAngle > currentAngle) {
                paintLineShort.setColor(colorBg);
            }
            canvas.drawArc(ovalLineShort, startAngle, 1, false, paintLineShort);
        }
        paintText.setTextAlign(Align.RIGHT);
        canvas.drawTextOnPath("" + minTemperture, pStart, 0, 0, paintText);
        paintText.setTextAlign(Align.LEFT);
        canvas.drawTextOnPath("" + maxTemperTure, pEnd, 0, 0, paintText);

        canvas.drawText("最高温度设置", 0, rLine, paintTextBottom);
        int currentTemp = (int) ((currentAngle - 135) / 270 * (maxTemperTure - minTemperture) + minTemperture + 0.5f);
        paintTextCenter.getTextBounds("99", 0, 2, bounds);
        canvas.drawText("" + currentTemp, 0, bounds.height() / 2, paintTextCenter);
        canvas.drawText("°", bounds.width() / 2 + 12, bounds.height() / 2, paintTextCenter);
        // canvas.drawLine(0, -rMax, 0, rMax, paintLineShort);
        canvas.restore();

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        double currentAngle = calculateAngle(event.getX(), event.getY());
        if (currentAngle >= 135 && currentAngle <= 405) {
            this.currentAngle = currentAngle;
            postInvalidate();
        } else {
            if (currentAngle - this.currentAngle > 0 && currentAngle - this.currentAngle < 45) {
                this.currentAngle = 405;
                postInvalidate();
            }
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            break;

        case MotionEvent.ACTION_MOVE:

            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:

            break;
        }
        return true;
    }

    private void handleTouch() {

    }

    // 根据触摸的点计算角度【以画布中心点为原点,角度大于135度】
    private double calculateAngle(float x, float y) {
        float pX = x - getWidth() / 2f;
        float pY = y - getHeight() / 2f;
        if (Math.sqrt(pX * pX + pY * pY) < rCircle) {
            return 0;// 手指在圆圈中触摸啥也不做
        }
        if (pX == 0) {
            return y > getHeight() / 2 ? 90 : 270;
        } else if (pY == 0) {
            return x > getWidth() / 2 ? 360 : 180;
        }
        double atan = Math.atan(Math.abs(pY) / Math.abs(pX));
        double angle = atan * 180 / Math.PI;
        // System.err.println("pi===="+atan+"====="+angle);
        if (x < getWidth() / 2) {

            // 90度到270度之间
            if (y > getHeight() / 2) {
                // 90到180
                return 180 - angle;
            } else {
                // 180---270
                return 180 + angle;
            }
        } else {
            if (y > getHeight() / 2) {
                // 360到450
                return 360 + angle;
            } else {
                // 270---360
                return 360 - angle;
            }
        }

    }
}

刻度盘那间隔线,我画的是圆弧,也可以如下画成线,选择自己喜欢的就好,效果图就是开头那图的下边那个

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class JustTestCanvas extends View{

    public JustTestCanvas(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(2);
    }

    Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.save();
        canvas.translate(getWidth()/2, getHeight()/2);
        canvas.rotate(135-90);
        for(int i=0;i<60;i++) {
            canvas.drawLine(0, 80, 0, 89, paint);
            canvas.rotate(4.5f);
        }
        canvas.restore();
    }
}