Android仪表盘自定义

只有最基本的表盘跟指针没弄动画。

 主要是onDraw方法

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.translate(mWidth / 2, mHeight / 2);//移动坐标原点到中心
    RectF rectF = new RectF(-mWidth/2 + padding,-mHeight/2+padding,mWidth/2-padding,mHeight/2-padding);
    canvas.drawArc(rectF,135,270,false,mCiclePaint);

    drawNum(canvas);//画仪表盘刻度

    drawerPointer(canvas,progress);//画指针

    drawCenterCircle(canvas);//画指针圆心

    drawProgressText(canvas); //画仪表盘进度值
}

仪表盘的刻度其实是通过旋转画布来画的,比如50刻度我只要drawLine一下 画一个竖直的线就行了,画它右边的在把画布旋转个2.7度再画一个竖线就行了类似的循环旋转画布,循环画竖线。

private void drawNum(Canvas canvas){
    canvas.save();
    canvas.rotate(-135,0,0);
    int indexY = -mHeight/2+10;
    canvas.drawLine(0,indexY+20,0,indexY+40,mScalePaint);

    float rAngle = 270/(100*1.0f);
    for (int i = 0; i <=100 ; i++) {
        canvas.save(); //记录画布状态
        canvas.rotate(rAngle * i, 0, 0);
        if (i==0 || i%5==0){
            canvas.drawLine(0,indexY+20,0,indexY+40,mScalePaint);
            if (i%10==0){
                canvas.drawText(i+"",-DisPlayUtils.dp2px(6),indexY+70,mTextPaint);
            }
        }else {
            canvas.drawLine(0,indexY+20,0,indexY+30,mScalePaint);
        }
        canvas.restore();
    }
    canvas.restore();
}

仪表盘外圈的drawArc画弧线的话,起始点要旋转135度,弧度270度才行。

canvas.drawArc(rectF,135,270,false,mCiclePaint);

rectF是一个矩形,只有top left bottom right 4个参数用来限制圆弧的位置不能超过这几个坐标,否则就不显示了。

画表盘的画笔我们指定只描边不要填充了,规定描边的宽度

mCiclePaint.setStyle(Paint.Style.STROKE);
mCiclePaint.setStrokeWidth(20);

画笔颜色的渐变是个

SweepGradient类 这个是控制弧形渐变的当然还有线性渐变等,不解释了。没怎么用过。

构造函数之一

public SweepGradient(float cx, float cy, @RecentlyNonNull int[] colors, @RecentlyNullable float[] positions) {}

圆心坐标,前2个,color是指颜色渐变的数组,颜色会从数组里的第一个渐变到最后一个,最后一个是positions也是一个数组跟colors对应,指定colors数组中的单个color渐变的比例默认是平分的,可以通过positions的大小来改变占用大小.positions如 0.1f,0.3f。2个数组长度保持一致,0.3f对应的颜色占的比例就是0.1的3倍了。

本例子中变盘colors中的第一个是蓝色,最有一个是红色,如果不用

Matrix gradientMatrix = new Matrix();
gradientMatrix.preRotate(135);来做旋转的话,蓝色的起始位置就会在园0度位置,而不是135度位置。

这样表盘的外面彩色的就画完了 里面的刻度通过循环旋转画line也可以完成,数值也是在循环为10的倍数时 drawLine的下方改变一下Y值。drawText就行。

最后是指针。

private void drawerPointer(Canvas canvas,float progress){
    canvas.save();
    canvas.rotate( -135+270/(100*1.0f)*progress);
    Path pointPath = new Path();
    RectF pointF = new RectF(-10,-10,10,10);
    pointPath.moveTo(0,-mWidth/4);
    pointPath.lineTo(-10,0);
    pointPath.addArc(pointF,0,180);
    pointPath.lineTo(0,-mWidth/4);
    canvas.drawPath(pointPath,mPointPaint);
    canvas.restore();
}

指针分为2个部分 一个三角形跟一个半圆,lineTo连接一个三角形,addArc来画半圆。组合成一个指针,指针旋转就通过旋转画布完成。

 

package com.yunhe.secondarywater.ui.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import com.yunhe.secondarywater.utils.DisPlayUtils;

/**
 * Created by wuzhi.peng on 2019/7/2
 **/
public class DashboardView extends View {

    private int padding = 20;


    private int mWidth;
    private int mHeight;

    private float progress;


    private Paint mScalePaint;
    private Paint mCiclePaint;
    private Paint mTextPaint;
    private Paint mPointPaint;
    private Paint mCenterCiclePaint;
    private Paint mProgressTextPaint;


    public DashboardView(Context context) {
        this(context,null);
    }

    public DashboardView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mScalePaint = new Paint();
        mScalePaint.setDither(true);
        mScalePaint.setAntiAlias(true);
        mScalePaint.setColor(Color.BLACK);
        mScalePaint.setStyle(Paint.Style.STROKE);
        mScalePaint.setStrokeWidth(2);
        mCiclePaint = new Paint();
        mCiclePaint.setDither(true);
        mCiclePaint.setAntiAlias(true);
        mCiclePaint.setStyle(Paint.Style.STROKE);
        mCiclePaint.setStrokeWidth(20);
        mTextPaint = new Paint();
        mTextPaint.setStyle(Paint.Style.STROKE);
        mTextPaint.setTextSize(DisPlayUtils.dp2px(12));
        mTextPaint.setAntiAlias(true);
        mTextPaint.setColor(Color.BLACK);
        mPointPaint = new Paint();
        mPointPaint.setAntiAlias(true);
        mPointPaint.setDither(true);
        mPointPaint.setColor(Color.RED);
        mCenterCiclePaint = new Paint();
        mCenterCiclePaint.setColor(Color.WHITE);
        mCenterCiclePaint.setAntiAlias(true);
        mCenterCiclePaint.setDither(true);

        mProgressTextPaint = new Paint();
        mProgressTextPaint.setDither(true);
        mProgressTextPaint.setAntiAlias(true);
        mProgressTextPaint.setStyle(Paint.Style.STROKE);
        mProgressTextPaint.setTextSize(DisPlayUtils.dp2px(20));


        SweepGradient gradient = new SweepGradient(0,0,new int[]{Color.parseColor("#3bc1ff"), Color.parseColor("#3fc6fa"),
                Color.parseColor("#5fc6d2"),Color.parseColor("#90c691"),Color.parseColor("#ccc643"),
                Color.parseColor("#fdc602"),Color.parseColor("#ff9300"),Color.parseColor("#ff5100"),
                Color.parseColor("#fa2300"),Color.parseColor("#ee0d07"),Color.parseColor("#d3162b"),},null);
        Matrix gradientMatrix = new Matrix();
        gradientMatrix.preRotate(135);
        gradient.setLocalMatrix(gradientMatrix);

        mCiclePaint.setShader(gradient);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = getWidth();
        mHeight = getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.translate(mWidth / 2, mHeight / 2);//移动坐标原点到中心
        RectF rectF = new RectF(-mWidth/2 + padding,-mHeight/2+padding,mWidth/2-padding,mHeight/2-padding);
        canvas.drawArc(rectF,135,270,false,mCiclePaint);

        drawNum(canvas);//画仪表盘刻度

        drawerPointer(canvas,progress);//画指针

        drawCenterCircle(canvas);//画指针圆心

        drawProgressText(canvas); //画仪表盘进度值
    }

    public void setProgress(float progress){
        if (progress<0)progress=0;
        if (progress>100)progress=100;
        this.progress = progress;
        invalidate();
    }


    private void drawNum(Canvas canvas){
        canvas.save();
        canvas.rotate(-135,0,0);
        int indexY = -mHeight/2+10;
        canvas.drawLine(0,indexY+20,0,indexY+40,mScalePaint);

        float rAngle = 270/(100*1.0f);
        for (int i = 0; i <=100 ; i++) {
            canvas.save(); //记录画布状态
            canvas.rotate(rAngle * i, 0, 0);
            if (i==0 || i%5==0){
                canvas.drawLine(0,indexY+20,0,indexY+40,mScalePaint);
                if (i%10==0){
                    canvas.drawText(i+"",-DisPlayUtils.dp2px(6),indexY+70,mTextPaint);
                }
            }else {
                canvas.drawLine(0,indexY+20,0,indexY+30,mScalePaint);
            }
            canvas.restore();
        }
        canvas.restore();
    }

    private void drawerPointer(Canvas canvas,float progress){
        canvas.save();
        canvas.rotate( -135+270/(100*1.0f)*progress);
        Path pointPath = new Path();
        RectF pointF = new RectF(-10,-10,10,10);
        pointPath.moveTo(0,-mWidth/4);
        pointPath.lineTo(-10,0);
        pointPath.addArc(pointF,0,180);
        pointPath.lineTo(0,-mWidth/4);
        canvas.drawPath(pointPath,mPointPaint);
        canvas.restore();
    }

    private void drawCenterCircle(Canvas canvas){
        canvas.drawCircle(0,0,5,mCenterCiclePaint);
    }

    private void drawProgressText(Canvas canvas){
        String text = progress+"%";
        if ( progress>=0 && progress<=60){
            mProgressTextPaint.setColor(Color.parseColor("#3bc1ff"));
        }else if (progress>60&&progress<=80){
            mProgressTextPaint.setColor(Color.parseColor("#ff5100"));
        }else if (progress>80){
            mProgressTextPaint.setColor(Color.parseColor("#ee0d07"));
        }
        canvas.drawText(progress+"%",-getTextLength(mProgressTextPaint,text)/2,mHeight/2-DisPlayUtils.dp2px(10),mProgressTextPaint);
    }

    private float getTextLength(Paint paint,String text){
        return paint.measureText(text);
    }
}

源码还是比较简单,没有搞很复杂,也没有用自定义的属性,不过用的时候宽高要一样不然就变形了这个要在onMesure的时候去搞一下 强制宽高相等取小的。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值