美文网首页
Android自定义View仪表

Android自定义View仪表

作者: LuckySuperMan | 来源:发表于2018-12-26 18:06 被阅读0次

先上效果图:

QQ20181226-180025-HD.gif

然后直接上代码:

public class InstrumentView extends View {
    private Paint mPaint;
    private Paint mPaint2;
    private Paint mPaint3;
    private Paint mPaint4;
    private Paint mPaint5;
    private Paint mPaint6;
    private ValueAnimator mValueAnimator;
    private int mValue;

    public InstrumentView(Context context) {
        super(context);
        init();
    }


    public InstrumentView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();

    }

    public InstrumentView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();

    }

    private void init() {
        //五段圆弧的画笔
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(40);
        mPaint.setColor(Color.parseColor("#cb393b"));
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        //白色圆弧的画笔
        mPaint2 = new Paint();
        mPaint2.setStyle(Paint.Style.STROKE);
        mPaint2.setAntiAlias(true);
        mPaint2.setStrokeWidth(80);
        mPaint2.setColor(Color.parseColor("#ffffff"));
        mPaint2.setStrokeCap(Paint.Cap.ROUND);

        //刻度虚线画笔
        mPaint3 = new Paint();
        mPaint3.setStyle(Paint.Style.STROKE);
        mPaint3.setAntiAlias(true);
        mPaint3.setStrokeWidth(5);
        mPaint3.setColor(Color.parseColor("#b8b8b8"));

        //指针线 画笔
        mPaint4 = new Paint();
        mPaint4.setStyle(Paint.Style.STROKE);
        mPaint4.setAntiAlias(true);
        mPaint4.setStrokeWidth(13);
        mPaint4.setColor(Color.parseColor("#3dbddf"));
        mPaint4.setStrokeCap(Paint.Cap.ROUND);

        //最小值 画笔
        mPaint5 = new Paint();
        mPaint5.setStyle(Paint.Style.STROKE);
        mPaint5.setAntiAlias(true);
        mPaint5.setColor(Color.parseColor("#000000"));
        mPaint5.setTextAlign(Paint.Align.CENTER);//设置文字对齐方式
        mPaint5.setTextSize(140);

        //最大值 画笔
        mPaint6 = new Paint();
        mPaint6.setStyle(Paint.Style.STROKE);
        mPaint6.setAntiAlias(true);
        mPaint6.setColor(Color.parseColor("#000000"));
        mPaint6.setTextAlign(Paint.Align.LEFT);//设置文字对齐方式
        mPaint6.setTextSize(30);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //这里为什么要收缩40:因为mPaint2.setStrokeWidth(80) 如果按照下面注释方法有一部分会绘制在画布外面
        //RectF oval = new RectF(0, 0,getWidth(), getWidth());
        RectF oval = new RectF(40, 40, getWidth() - 40, getWidth() - 40);

        //白色背景
        canvas.drawArc(oval, 0, -180, false, mPaint2);

        //五段圆弧
        mPaint.setColor(Color.parseColor("#cb393b"));
        canvas.drawArc(oval, 0, -180 / 5, false, mPaint);

        mPaint.setColor(Color.parseColor("#ff4a5b"));
        canvas.drawArc(oval, -180 / 5, -180 / 5, false, mPaint);

        mPaint.setColor(Color.parseColor("#ffdb82"));
        canvas.drawArc(oval, -180 * 2 / 5, -180 / 5, false, mPaint);

        mPaint.setColor(Color.parseColor("#75cd80"));
        canvas.drawArc(oval, -180 * 3 / 5, -180 / 5, false, mPaint);

        mPaint.setColor(Color.parseColor("#85dff6"));
        canvas.drawArc(oval, -180 * 4 / 5, -180 / 5, false, mPaint);


        //画刻度(总共31个刻度、第一个和最后一个长度增加颜色加深)
        for (int i = 0; i <= 30; i++) {
            int weight;
            if (i == 30 || i == 0) {
                mPaint3.setColor(Color.parseColor("#000000"));
                weight = 30;
            } else {
                mPaint3.setColor(Color.parseColor("#b8b8b8"));
                weight = 20;

            }
            //起始点80 + 20:80是白色圆弧的宽度、20是间隙
            int startX = 80 + 20;
            canvas.drawLine(startX, getWidth() / 2, startX + weight, getWidth() / 2, mPaint3);
            canvas.save();
            //逆时针旋转180 / 30度(最后一个刻度 不用旋转画布)
            if (i != 30) {
                canvas.rotate(180 / 30, getWidth() / 2, getWidth() / 2);
            }

        }

        //把画布旋转回来
        canvas.rotate(-180, getWidth() / 2, getWidth() / 2);

        //画指针(一条线、一个箭头)
        canvas.rotate((float) mValue / 10, getWidth() / 2, getWidth() / 2);
        canvas.save();
        //线
        canvas.drawLine(10, getWidth() / 2, 70, getWidth() / 2, mPaint4);

        //箭头
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.jiantou);
        int bitmapWidth = bitmap.getWidth();
        int bitmapHeight = bitmap.getHeight();
        canvas.drawBitmap(bitmap, null, new Rect(100, getWidth() / 2 - bitmapHeight / 2,
                100 + bitmapWidth, getWidth() / 2 + bitmapHeight / 2), null);

        //把画布旋转回来
        canvas.rotate(-(float) mValue / 10, getWidth() / 2, getWidth() / 2);


        //画 文字(文字绘制到圆的中心位置)
        Rect textRect = new Rect(0, 0, getWidth(), getWidth());
        Paint.FontMetricsInt fontMetrics = mPaint5.getFontMetricsInt();
        //获取基线
        int baseline = (textRect.bottom + textRect.top - fontMetrics.bottom - fontMetrics.top) / 2;
        canvas.drawText(mValue / 10 + "斤肉", textRect.centerX(), baseline, mPaint5);

        //画最小值
        mPaint6.setTextAlign(Paint.Align.LEFT);//左对齐方式
        canvas.drawText("0", 150, getWidth() / 2 + 15, mPaint6);
        //画最大值
        mPaint6.setTextAlign(Paint.Align.RIGHT);//右对齐方式
        canvas.drawText("180", getWidth() - 150, getWidth() / 2 + 15, mPaint6);

    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        // 在wrap_content的情况下默认长度为widthSpecSize * 3 / 5
        int minSize = widthSpecSize * 3 / 5;
        // wrap_content的specMode是AT_MOST模式,这种情况下宽/高等同于specSize
        // 查表得这种情况下specSize等同于parentSize,也就是父容器当前剩余的大小
        // 在wrap_content的情况下如果特殊处理,效果等同martch_parent
        if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, minSize);
        } else if (widthSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(minSize, heightSpecSize);
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSpecSize, minSize);
        }
    }

    public void setValue(int weight) {
        mValueAnimator = ValueAnimator.ofInt(0, weight * 10);
        mValueAnimator.setDuration(3000);
        mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                mValue = (int) valueAnimator.getAnimatedValue();
                invalidate();
            }
        });
        mValueAnimator.start();
    }
}

相关文章

网友评论

      本文标题:Android自定义View仪表

      本文链接:https://www.haomeiwen.com/subject/qlcklqtx.html