Android仪表盘自定View

package com.example.awesome;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;


public class DashboardView extends View {
    private int mFirstRangeColor;
    private int mSecondRangeColor;
    private int mThirdRangeColor;
    private int mStartAngle;
    private int mSweepAngle;
    private int mMin;
    private int mMax;
    private int mSection;
    private int mPortion;
    private String mHeaderText;
    private int mValue;
    private boolean isShowValueText;
    private boolean isShowPointerRange;
    private float mLineStrokeWidth;
    private float mColorStrokeWidth;
    private float mColorArcPadding;
    private float mLongScaleLength;
    private float mShortScaleLength;
    private int mScaleColor;
    private int mPointerColor;
    private int mMinPointerColor;
    private int mMaxPointerColor;
    private float mScaleTextSize;
    private int mHeaderTextColor;
    private float mHeaderTextSize;
    private int mFirstRange;
    private int mSecondRange;
    private int mPLRadius;
    private int mPSRadius;
    private int mRadius;
    private int mPadding;
    private float mCenterX;
    private float mCenterY;
    private Paint mPaint;
    private RectF mRectFColorArc;
    private RectF mRectFLineArc;
    private RectF mRectFInnerArc;
    private Path mPath;
    private Rect mRectText;
    private String[] mTexts;
    private int mMinValue;
    private int mMaxValue;

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

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

    public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mFirstRangeColor = -65536;
        this.mSecondRangeColor = -1024;
        this.mThirdRangeColor = -14025425;
        this.mStartAngle = 180;
        this.mSweepAngle = 180;
        this.mMin = 0;
        this.mMax = 100;
        this.mSection = 10;
        this.mPortion = 10;
        this.mHeaderText = "Header";
        this.mValue = this.mMin;
        this.isShowValueText = true;
        this.isShowPointerRange = true;
        this.mLineStrokeWidth = 2.0F;
        this.mColorStrokeWidth = 10.0F;
        this.mColorArcPadding = 10.0F;
        this.mLongScaleLength = 18.0F;
        this.mShortScaleLength = 15.0F;
        this.mScaleColor = -1;
        this.mPointerColor = -1;
        this.mMinPointerColor = -6381922;
        this.mMaxPointerColor = -6381922;
        this.mScaleTextSize = 30.0F;
        this.mHeaderTextColor = -1;
        this.mHeaderTextSize = 30.0F;
        this.mFirstRange = 40;
        this.mSecondRange = 40;
        this.mMinValue = this.mValue;
        this.mMaxValue = this.mValue;
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DashboardView, 0, 0);
        this.mFirstRangeColor = a.getColor(R.styleable.DashboardView_dbv_firstColor, this.mFirstRangeColor);
        this.mSecondRangeColor = a.getColor(R.styleable.DashboardView_dbv_secondColor, this.mSecondRangeColor);
        this.mThirdRangeColor = a.getColor(R.styleable.DashboardView_dbv_thirdColor, this.mThirdRangeColor);
        this.mMax = a.getInteger(R.styleable.DashboardView_dbv_max, this.mMax);
        this.mMin = a.getInteger(R.styleable.DashboardView_dbv_min, this.mMin);
        this.mLineStrokeWidth = a.getDimension(R.styleable.DashboardView_dbv_lineWidth, this.mLineStrokeWidth);
        this.mColorStrokeWidth = a.getDimension(R.styleable.DashboardView_dbv_colorWidth, this.mColorStrokeWidth);
        this.mColorArcPadding = a.getDimension(R.styleable.DashboardView_dbv_colorPadding, this.mColorArcPadding);
        this.mLongScaleLength = a.getDimension(R.styleable.DashboardView_dbv_longScaleLength, this.mLongScaleLength);
        this.mShortScaleLength = a.getDimension(R.styleable.DashboardView_dbv_shortScaleLength, this.mShortScaleLength);
        this.mStartAngle = a.getInteger(R.styleable.DashboardView_dbv_startAngle, this.mStartAngle);
        this.mSweepAngle = a.getInteger(R.styleable.DashboardView_dbv_sweepAngle, this.mSweepAngle);
        this.mSection = a.getInteger(R.styleable.DashboardView_dbv_section, this.mSection);
        this.mPortion = a.getInteger(R.styleable.DashboardView_dbv_portion, this.mPortion);
        this.mValue = a.getInteger(R.styleable.DashboardView_dbv_value, this.mValue);
        this.isShowValueText = a.getBoolean(R.styleable.DashboardView_dbv_showValueText, this.isShowValueText);
        this.isShowPointerRange = a.getBoolean(R.styleable.DashboardView_dbv_showPointerRange, this.isShowPointerRange);
        this.mFirstRange = a.getInteger(R.styleable.DashboardView_dbv_firstRange, this.mFirstRange);
        this.mSecondRange = a.getInteger(R.styleable.DashboardView_dbv_secondRange, this.mSecondRange);
        this.mScaleColor = a.getColor(R.styleable.DashboardView_dbv_scaleColor, this.mScaleColor);
        this.mPointerColor = a.getColor(R.styleable.DashboardView_dbv_pointerColor, this.mPointerColor);
        this.mMinPointerColor = a.getColor(R.styleable.DashboardView_dbv_minPointerColor, this.mMinPointerColor);
        this.mMaxPointerColor = a.getColor(R.styleable.DashboardView_dbv_maxPointerColor, this.mMaxPointerColor);
        this.mScaleTextSize = a.getDimension(R.styleable.DashboardView_dbv_scaleTextSize, this.mScaleTextSize);
        this.mHeaderTextColor = a.getColor(R.styleable.DashboardView_dbv_headerTextColor, this.mHeaderTextColor);
        this.mHeaderTextSize = a.getDimension(R.styleable.DashboardView_dbv_headerTextSize, this.mHeaderTextSize);
        this.mHeaderText = a.getString(R.styleable.DashboardView_dbv_headerText);
        a.recycle();
        this.init();
    }

    private void init() {
        this.mPSRadius = this.dp2px(10);
        this.mPaint = new Paint();
        this.mPaint.setAntiAlias(true);
        this.mRectFColorArc = new RectF();
        this.mRectFLineArc = new RectF();
        this.mRectFInnerArc = new RectF();
        this.mPath = new Path();
        this.mRectText = new Rect();
        this.mTexts = new String[this.mSection + 1];

        for(int i = 0; i < this.mTexts.length; ++i) {
            int n = (this.mMax - this.mMin) / this.mSection;
            this.mTexts[i] = String.valueOf(this.mMin + i * n);
        }

    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.mPadding = Math.max(Math.max(this.getPaddingLeft(), this.getPaddingTop()), Math.max(this.getPaddingRight(), this.getPaddingBottom()));
        this.setPadding(this.mPadding, this.mPadding, this.mPadding, this.mPadding);
        int width = resolveSize(this.dp2px(200), widthMeasureSpec);
        this.mRadius = (int)((float)(width / 2 - this.mPadding) - this.mLineStrokeWidth - this.mColorStrokeWidth - this.mColorArcPadding);
        this.mPaint.setTextSize(this.mHeaderTextSize);
        if (this.isShowValueText) {
            this.mPaint.getTextBounds("0", 0, "0".length(), this.mRectText);
        } else {
            this.mPaint.getTextBounds("0", 0, 0, this.mRectText);
        }

        int height = (int)((float)this.mRadius + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding + (float)this.mPSRadius + (float)(this.mRectText.height() * 3));
        float[] startPoint = this.getCoordinatePoint(this.mRadius, (float)this.mStartAngle);
        float[] endPoint = this.getCoordinatePoint(this.mRadius, (float)(this.mStartAngle + this.mSweepAngle));
        int maxHeight = (int)Math.max((float)height, Math.max(startPoint[1] + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding, endPoint[1] + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding));
        height = maxHeight + this.getPaddingTop() + this.getPaddingBottom();
        this.setMeasuredDimension(width, height);
        this.mCenterX = this.mCenterY = (float)this.getMeasuredWidth() / 2.0F;
        this.mRectFColorArc.set((float)this.getPaddingLeft() + this.mColorStrokeWidth, (float)this.getPaddingTop() + this.mColorStrokeWidth, (float)(this.getMeasuredWidth() - this.getPaddingRight()) - this.mColorStrokeWidth, (float)(this.getMeasuredWidth() - this.getPaddingBottom()) - this.mColorStrokeWidth);
        this.mRectFLineArc.set(this.mRectFColorArc.left + this.mColorArcPadding + this.mLineStrokeWidth, this.mRectFColorArc.top + this.mColorArcPadding + this.mLineStrokeWidth, this.mRectFColorArc.right - this.mColorArcPadding - this.mLineStrokeWidth, this.mRectFColorArc.bottom - this.mColorArcPadding - this.mLineStrokeWidth);
        this.mPaint.setTextSize(this.mScaleTextSize);
        this.mPaint.getTextBounds("0", 0, "0".length(), this.mRectText);
        this.mRectFInnerArc.set(this.mRectFLineArc.left + this.mLongScaleLength + (float)this.mRectText.height() + (float)this.dp2px(3), this.mRectFLineArc.top + this.mLongScaleLength + (float)this.mRectText.height() + (float)this.dp2px(3), this.mRectFLineArc.right - this.mLongScaleLength - (float)this.mRectText.height() - (float)this.dp2px(3), this.mRectFLineArc.bottom - this.mLongScaleLength - (float)this.mRectText.height() - (float)this.dp2px(3));
        this.mPLRadius = (int)((float)this.mRadius - (this.mShortScaleLength + (float)this.mRectText.height() + (float)this.dp2px(5)));
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        this.mPaint.setStyle(Paint.Style.STROKE);
        this.mPaint.setStrokeWidth(this.mColorStrokeWidth);
        this.mPaint.setColor(this.mThirdRangeColor);

        canvas.drawArc(this.mRectFColorArc, (float)this.mStartAngle, (float)this.mSweepAngle, false, this.mPaint);
        this.mPaint.setColor(this.mSecondRangeColor);
        Log.d("YSH",""+mStartAngle+"    "+mSweepAngle * (this.mFirstRange + this.mSecondRange) / 100);
        canvas.drawArc(this.mRectFColorArc, (float)this.mStartAngle, (float)(this.mSweepAngle * (this.mFirstRange + this.mSecondRange) / 100), false, this.mPaint);
        this.mPaint.setColor(this.mFirstRangeColor);
        canvas.drawArc(this.mRectFColorArc, (float)this.mStartAngle, (float)(this.mSweepAngle * this.mFirstRange / 100), false, this.mPaint);
        this.mPaint.setStyle(Paint.Style.STROKE);
        this.mPaint.setStrokeWidth(this.mLineStrokeWidth);
        this.mPaint.setColor(this.mScaleColor);
        canvas.drawArc(this.mRectFLineArc, (float)this.mStartAngle, (float)this.mSweepAngle, false, this.mPaint);
        double cos = Math.cos(Math.toRadians((double)(this.mStartAngle - 180)));
        double sin = Math.sin(Math.toRadians((double)(this.mStartAngle - 180)));
        float x0 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding) + (double)this.mRadius * (1.0D - cos));
        float y0 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding) + (double)this.mRadius * (1.0D - sin));
        float x1 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding + (float)this.mRadius) - (double)((float)this.mRadius - this.mLongScaleLength) * cos);
        float y1 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding + (float)this.mRadius) - (double)((float)this.mRadius - this.mLongScaleLength) * sin);
        canvas.save();
        canvas.drawLine(x0, y0, x1, y1, this.mPaint);
        float angle = (float)this.mSweepAngle * 1.0F / (float)this.mSection;

        for(int i = 0; i < this.mSection; ++i) {
            canvas.rotate(angle, this.mCenterX, this.mCenterY);
            canvas.drawLine(x0, y0, x1, y1, this.mPaint);
        }

        canvas.restore();
        canvas.save();
        this.mPaint.setStrokeWidth(1.0F);
        float x2 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding + (float)this.mRadius) - (double)((float)this.mRadius - this.mLongScaleLength / 2.0F) * cos);
        float y2 = (float)((double)((float)this.mPadding + this.mLineStrokeWidth + this.mColorStrokeWidth + this.mColorArcPadding + (float)this.mRadius) - (double)((float)this.mRadius - this.mLongScaleLength / 2.0F) * sin);
        canvas.drawLine(x0, y0, x2, y2, this.mPaint);
        angle = (float)this.mSweepAngle * 1.0F / (float)(this.mSection * this.mPortion);

        int i;
        for(i = 1; i < this.mSection * mPortion; ++i) {
            canvas.rotate(angle, this.mCenterX, mCenterY);
            if (i % mPortion != 0) {
                canvas.drawLine(x0, y0, x2, y2, mPaint);
            }
        }

        canvas.restore();
        this.mPaint.setTextSize(this.mScaleTextSize);
        this.mPaint.setTextAlign(Paint.Align.LEFT);
        this.mPaint.setStyle(Paint.Style.FILL);

        for(i = 0; i < this.mTexts.length; ++i) {
            this.mPaint.getTextBounds(this.mTexts[i], 0, this.mTexts[i].length(), this.mRectText);
            float θ = (float)((double)(180 * this.mRectText.width() / 2) / (3.141592653589793D * (double)((float)this.mRadius - this.mLongScaleLength - (float)this.mRectText.height())));
            this.mPath.reset();
            this.mPath.addArc(this.mRectFInnerArc, (float)(this.mStartAngle + i * (this.mSweepAngle / this.mSection)) - θ, (float)this.mSweepAngle);
            canvas.drawTextOnPath(this.mTexts[i], this.mPath, 0.0F, 0.0F, this.mPaint);
        }

        if (!TextUtils.isEmpty(this.mHeaderText)) {
            this.mPaint.setColor(this.mHeaderTextColor);
            this.mPaint.setTextSize(this.mHeaderTextSize);
            this.mPaint.setTextAlign(Paint.Align.CENTER);
            this.mPaint.getTextBounds(this.mHeaderText, 0, this.mHeaderText.length(), this.mRectText);
            canvas.drawText(this.mHeaderText, this.mCenterX, this.mCenterY / 2.0F + (float)this.mRectText.height(), this.mPaint);
        }

        this.drawPointer(canvas, this.mValue, this.mPointerColor);
        if (this.isShowPointerRange) {
            this.drawPointer(canvas, this.mMinValue, this.mMinPointerColor);
            this.drawPointer(canvas, this.mMaxValue, this.mMaxPointerColor);
        }

        this.mPaint.setColor(-16777216);
        canvas.drawCircle(this.mCenterX, this.mCenterY, (float)this.dp2px(2), this.mPaint);
        if (isShowValueText) {
            this.mPaint.setTextSize((float)this.sp2px(16));
            this.mPaint.setTextAlign(Paint.Align.CENTER);
            this.mPaint.setColor(this.mHeaderTextColor);
            String value = String.valueOf(this.mValue);
            this.mPaint.getTextBounds(value, 0, value.length(), this.mRectText);
            canvas.drawText(value, this.mCenterX, this.mCenterY + (float)this.mPSRadius + (float)(this.mRectText.height() * 2), this.mPaint);
        }

    }

    private void drawPointer(Canvas canvas, int value, int color) {
        float θ = (float)(this.mStartAngle + this.mSweepAngle * (value - this.mMin) / (this.mMax - this.mMin));
        int d = this.dp2px(5);
        this.mPath.reset();
        float[] p1 = this.getCoordinatePoint(d, θ - 90.0F);
        this.mPath.moveTo(p1[0], p1[1]);
        float[] p2 = this.getCoordinatePoint(this.mPLRadius, θ);
        this.mPath.lineTo(p2[0], p2[1]);
        float[] p3 = this.getCoordinatePoint(d, θ + 90.0F);
        this.mPath.lineTo(p3[0], p3[1]);
        float[] p4 = this.getCoordinatePoint(this.mPSRadius, θ - 180.0F);
        this.mPath.lineTo(p4[0], p4[1]);
        this.mPath.close();
        this.mPaint.setColor(color);
        canvas.drawPath(this.mPath, this.mPaint);
    }

    private int dp2px(int dp) {
        return (int) TypedValue.applyDimension(1, (float)dp, Resources.getSystem().getDisplayMetrics());
    }

    private int sp2px(int sp) {
        return (int)TypedValue.applyDimension(2, (float)sp, Resources.getSystem().getDisplayMetrics());
    }

    public float[] getCoordinatePoint(int radius, float angle) {
        float[] point = new float[2];
        double arcAngle = Math.toRadians((double)angle);
        if (angle < 90.0F) {
            point[0] = (float)((double)this.mCenterX + Math.cos(arcAngle) * (double)radius);
            point[1] = (float)((double)this.mCenterY + Math.sin(arcAngle) * (double)radius);
        } else if (angle == 90.0F) {
            point[0] = this.mCenterX;
            point[1] = this.mCenterY + (float)radius;
        } else if (angle > 90.0F && angle < 180.0F) {
            arcAngle = 3.141592653589793D * (double)(180.0F - angle) / 180.0D;
            point[0] = (float)((double)this.mCenterX - Math.cos(arcAngle) * (double)radius);
            point[1] = (float)((double)this.mCenterY + Math.sin(arcAngle) * (double)radius);
        } else if (angle == 180.0F) {
            point[0] = this.mCenterX - (float)radius;
            point[1] = this.mCenterY;
        } else if (angle > 180.0F && angle < 270.0F) {
            arcAngle = 3.141592653589793D * (double)(angle - 180.0F) / 180.0D;
            point[0] = (float)((double)this.mCenterX - Math.cos(arcAngle) * (double)radius);
            point[1] = (float)((double)this.mCenterY - Math.sin(arcAngle) * (double)radius);
        } else if (angle == 270.0F) {
            point[0] = this.mCenterX;
            point[1] = this.mCenterY - (float)radius;
        } else {
            arcAngle = 3.141592653589793D * (double)(360.0F - angle) / 180.0D;
            point[0] = (float)((double)this.mCenterX + Math.cos(arcAngle) * (double)radius);
            point[1] = (float)((double)this.mCenterY - Math.sin(arcAngle) * (double)radius);
        }

        return point;
    }

    public int getValue() {
        return this.mValue;
    }

    public void setValue(int value) {
        if (this.mValue != value) {
            if (value < this.mMin) {
                this.mValue = this.mMin;
            } else if (value > this.mMax) {
                this.mValue = this.mMax;
            } else {
                this.mValue = value;
            }

            if (this.mValue < this.mMinValue) {
                this.mMinValue = this.mValue;
            }

            if (this.mValue > this.mMaxValue) {
                this.mMaxValue = this.mValue;
            }

            this.postInvalidate();
        }
    }

    public void resetValue(int value) {
        if (value < this.mMin) {
            this.mValue = this.mMin;
        } else if (value > this.mMax) {
            this.mValue = this.mMax;
        } else {
            this.mValue = value;
        }

        this.mMinValue = this.mValue;
        this.mMaxValue = this.mValue;
        this.postInvalidate();
    }

    public int getFirstRange() {
        return this.mFirstRange;
    }

    public void setFirstRange(int firstRange) {
        this.mFirstRange = firstRange;
        this.postInvalidate();
    }

    public int getSecondRange() {
        return this.mSecondRange;
    }

    public void setSecondRange(int secondRange) {
        this.mSecondRange = secondRange;
        this.postInvalidate();
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想不上班

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值