package com.moral.yunfushao.ui; import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.SweepGradient; import android.graphics.drawable.BitmapDrawable; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.view.animation.Animation; import com.moral.yunfushao.R; /** * 轮盘 * Created by haijiang on 2017/6/20. */ public class PanelView extends View { private Context mContext; private int mWidth; private int mmWidth; private int mmHeight; //绘制渐变圆弧的画笔 private Paint mShaderPaint; private int[] mshaderColor = new int[]{0xfff70e17, 0xfff70e17, 0xfff70e17, 0xffff5c92, 0xff00c44a, 0xff00d062, 0xff00f5af, 0xff00f6cb, 0xff00ccff, 0xff179fff, 0xffa054ff, 0xffa53aff, 0xffd74bff, 0xfff64da5, 0xfff70e17}; private int[] mshaderRedColor = new int[]{0xfff70e17, 0xffff5c92}; private int[] mshaderZiseColor = new int[]{0xffa53aff, 0xffd74bff, 0xfff64da5}; private int[] mshaderBlueColor = new int[]{0xff00f6cb, 0xff00ccff, 0xff179fff, 0xffa054ff}; private int[] mshaderGreenColor = new int[]{0xff00c44a, 0xff00d062, 0xff00f5af}; //环形渐变色值渲染 private SweepGradient mSweepGradient; private int mShaderWidth = 70; //画圆环上的线 private Paint paintGapLine; //小格子线颜色3°画一次 private int line1Color = 0xffb8e8f4; //小格子线颜色15°画一次 private int line2Color = 0xff7ed3ff; //小格子线颜色60°画一次 private int line3Color = 0xff009cff; //短线长度 private int line1Length = 50; //长线长度 private int line2Length = 70; private int lineWidth = 6; //内外间隔 private int widthInner = 120; private int paddingKedu = 40; private Paint mLinePaint; //画刻度文字 private Paint drawTextPaint; private int textColor = Color.GRAY; private int textSize = 36; private String[] level = {"安全状态", "建议回避", "及时闪躲", "紧急撤离"}; //内进度圆 private Paint mCirclePaint; private int innerCircleColor = 0xffb8e8f4; private int mCircleWidth = 70; private int innerPadding = 20; //画进度 private Paint mProgressPaint; private int progressCircleColor = 0xff53c9ff; //画指针 private Paint mBitPaint; private Bitmap mBitmap; private float percent = 0;//百分比数据 private float percent2 = 0;//百分比数据 private String statusStr = "未连接"; private ValueAnimator anim; public void setStatusStr(String statusStr) { this.statusStr = statusStr; postInvalidate(); } public void setPercent(float percent) { this.percent2 = percent; startAnimation(); } public PanelView(Context context) { super(context); init(context); } public PanelView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(context); } public PanelView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context mContext) { this.mContext = mContext; //初始化 mShaderWidth = dip2px(mContext, 24); line1Length = dip2px(mContext, 14); line2Length = dip2px(mContext, 22); lineWidth = dip2px(mContext, 2); widthInner = dip2px(mContext, 40); paddingKedu = dip2px(mContext, 10); mCircleWidth = dip2px(mContext, 24); innerPadding = dip2px(mContext, 8); textSize = dip2px(mContext, 12); //渐变圆环 mShaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mShaderPaint.setStyle(Paint.Style.STROKE); mShaderPaint.setStrokeWidth(mShaderWidth); mShaderPaint.setStrokeCap(Paint.Cap.ROUND); paintGapLine = new Paint(Paint.ANTI_ALIAS_FLAG); paintGapLine.setColor(Color.WHITE); paintGapLine.setStrokeWidth(dip2px(mContext, 3)); //刻度 mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLinePaint.setStyle(Paint.Style.STROKE); mLinePaint.setStrokeWidth(lineWidth); mLinePaint.setColor(line1Color); //文字 drawTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); drawTextPaint.setColor(textColor); drawTextPaint.setTextSize(textSize); //内进度圆 mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaint.setStyle(Paint.Style.STROKE); mCirclePaint.setStrokeWidth(mCircleWidth); mCirclePaint.setStrokeCap(Paint.Cap.ROUND); mCirclePaint.setColor(innerCircleColor); //画进度 mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mProgressPaint.setStyle(Paint.Style.STROKE); mProgressPaint.setStrokeWidth(mCircleWidth); mProgressPaint.setStrokeCap(Paint.Cap.ROUND); mProgressPaint.setColor(progressCircleColor); //画指针 mBitPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBitPaint.setFilterBitmap(true); mBitPaint.setDither(true); mBitmap = ((BitmapDrawable) mContext.getResources().getDrawable(R.mipmap.zhizhen)).getBitmap(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY) { mmWidth = widthSize; } else { mmWidth = dip2px(mContext, 300); } if (heightMode == MeasureSpec.EXACTLY) { mmHeight = heightSize; } else { mmHeight = dip2px(mContext, 300); } mWidth = mmWidth < mmHeight ? mmWidth : mmHeight; setMeasuredDimension(mmWidth, mmHeight); } private void startAnimation() { anim = ValueAnimator.ofFloat((float) percent, percent2); anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { percent = (float) animation.getAnimatedValue(); postInvalidate(); } }); anim.setDuration(3000L); anim.setRepeatCount(Animation.INFINITE); anim.start(); } // // private class CustomPointEvaluator implements TypeEvaluator { // @Override // public Float evaluate(float fraction, Float startValue, Float endValue) { // System.out.println("chenqi2 rotato " + fraction + " all -> " + endValue); // float y = fraction * endValue; // return y; // } // } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画刻度 drawKedu(canvas); //画刻度文字 drawTextKedu(canvas); //画渐变圆环 drawJianbianCircle(canvas); //画内圆 RectF cirlcleRect = new RectF(mShaderWidth + widthInner + mCircleWidth + innerPadding, mShaderWidth + widthInner + mCircleWidth + innerPadding, mWidth - mShaderWidth - widthInner - mCircleWidth - innerPadding, mWidth - mShaderWidth - widthInner - mCircleWidth - innerPadding); canvas.drawArc(cirlcleRect, 0, 360, false, mCirclePaint); //画指针 float circleR = (cirlcleRect.right - cirlcleRect.left) / 2; float bitH = circleR; float bitW = bitH * 0.448f; canvas.save(); canvas.rotate(percent * 300 - 150, mWidth / 2, mWidth / 2); RectF btmRect = new RectF((float) (cirlcleRect.left + bitH - bitW * 0.535), (float) (cirlcleRect.top + mCircleWidth * 0.68), (float) (cirlcleRect.left + bitH + bitW * 0.465), (float) (cirlcleRect.top + bitH + mCircleWidth * 0.68)); // Log.d("haijiang","left="+btmRect.left); // Log.d("haijiang","right="+btmRect.right); // Log.d("haijiang","top="+btmRect.top); // Log.d("haijiang","bottom="+btmRect.bottom); // Log.d("haijiang","宽高比例="+(btmRect.right-btmRect.left)/(btmRect.bottom-btmRect.top)); canvas.drawBitmap(mBitmap, null, btmRect, mBitPaint); canvas.restore(); drawTextPaint.setColor(line3Color); drawTextPaint.setTextSize(textSize); int statusStrWidth = (int) drawTextPaint.measureText(this.statusStr); canvas.drawText(this.statusStr, mWidth / 2 - statusStrWidth / 2, mWidth / 2 + (btmRect.bottom - btmRect.top) / 2, drawTextPaint); if (percent > 0) canvas.drawArc(new RectF(mShaderWidth + widthInner + mCircleWidth + innerPadding, mShaderWidth + widthInner + mCircleWidth + innerPadding, mWidth - mShaderWidth - widthInner - mCircleWidth - innerPadding, mWidth - mShaderWidth - widthInner - mCircleWidth - innerPadding), 120, 300 * percent, false, mProgressPaint); } /** * 画刻度 * * @param canvas */ private void drawKedu(Canvas canvas) { //画右边刻度 for (int i = 0; i <= 50; i++) { canvas.save(); if (i % 5 == 0) { mLinePaint.setColor(line2Color); canvas.rotate(i * 3, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, paddingKedu, mWidth / 2, line2Length + paddingKedu, mLinePaint); } else { mLinePaint.setColor(line1Color); canvas.rotate(i * 3, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, paddingKedu, mWidth / 2, line1Length + paddingKedu, mLinePaint); } canvas.restore(); } //画右边刻度 for (int j = 0; j <= 50; j++) { canvas.save(); if (j % 5 == 0) { mLinePaint.setColor(line2Color); canvas.rotate(-j * 3, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, paddingKedu, mWidth / 2, line2Length + paddingKedu, mLinePaint); } else { mLinePaint.setColor(line1Color); canvas.rotate(-j * 3, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, paddingKedu, mWidth / 2, line1Length + paddingKedu, mLinePaint); } canvas.restore(); } } /** * 画刻度文字 * * @param canvas */ private void drawTextKedu(Canvas canvas) { for (int i = 0; i < level.length; i++) { float textWidth = drawTextPaint.measureText(level[i]); if (percent < 0.25) { if (i == 0) { drawTextPaint.setColor(line3Color); } else { drawTextPaint.setColor(Color.GRAY); } canvas.save(); if (i == 0) { canvas.rotate(-120, mWidth / 2, mWidth / 2); } else if (i == 1) { canvas.rotate(-45, mWidth / 2, mWidth / 2); } else if (i == 2) { canvas.rotate(45, mWidth / 2, mWidth / 2); } else if (i == 3) { canvas.rotate(120, mWidth / 2, mWidth / 2); } canvas.drawText(level[i], mWidth / 2 - textWidth / 2, paddingKedu + line2Length + textSize, drawTextPaint); canvas.restore(); } else if (percent >= 0.25 && percent < 0.5) { if (i == 1) { drawTextPaint.setColor(line3Color); } else { drawTextPaint.setColor(Color.GRAY); } canvas.save(); // canvas.rotate(-120+i*75,mWidth/2,mWidth/2); if (i == 0) { canvas.rotate(-120, mWidth / 2, mWidth / 2); } else if (i == 1) { canvas.rotate(-45, mWidth / 2, mWidth / 2); } else if (i == 2) { canvas.rotate(45, mWidth / 2, mWidth / 2); } else if (i == 3) { canvas.rotate(120, mWidth / 2, mWidth / 2); } canvas.drawText(level[i], mWidth / 2 - textWidth / 2, paddingKedu + line2Length + textSize, drawTextPaint); canvas.restore(); } else if (percent >= 0.5 && percent < 0.75) { if (i == 2) { drawTextPaint.setColor(line3Color); } else { drawTextPaint.setColor(Color.GRAY); } canvas.save(); // canvas.rotate(-120+i*75,mWidth/2,mWidth/2); if (i == 0) { canvas.rotate(-120, mWidth / 2, mWidth / 2); } else if (i == 1) { canvas.rotate(-45, mWidth / 2, mWidth / 2); } else if (i == 2) { canvas.rotate(45, mWidth / 2, mWidth / 2); } else if (i == 3) { canvas.rotate(120, mWidth / 2, mWidth / 2); } canvas.drawText(level[i], mWidth / 2 - textWidth / 2, paddingKedu + line2Length + textSize, drawTextPaint); canvas.restore(); } else if (percent >= 0.75) { if (i == 3) { drawTextPaint.setColor(line3Color); } else { drawTextPaint.setColor(Color.GRAY); } canvas.save(); // canvas.rotate(-105+i*75,mWidth/2,mWidth/2); if (i == 0) { canvas.rotate(-120, mWidth / 2, mWidth / 2); } else if (i == 1) { canvas.rotate(-45, mWidth / 2, mWidth / 2); } else if (i == 2) { canvas.rotate(45, mWidth / 2, mWidth / 2); } else if (i == 3) { canvas.rotate(120, mWidth / 2, mWidth / 2); } canvas.drawText(level[i], mWidth / 2 - textWidth / 2, paddingKedu + line2Length + textSize, drawTextPaint); canvas.restore(); } } } /** * 画渐变圆环 * * @param canvas */ private void drawJianbianCircle(Canvas canvas) { mSweepGradient = new SweepGradient(mWidth / 2, mWidth / 2, mshaderColor, null); mShaderPaint.setShader(mSweepGradient); canvas.drawArc(new RectF(mShaderWidth + widthInner, mShaderWidth + widthInner, mWidth - mShaderWidth - widthInner, mWidth - mShaderWidth - widthInner), 120, 300, false, mShaderPaint); //画圆环分隔 canvas.save(); canvas.rotate(75, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, line2Length + paddingKedu * 3, mWidth / 2, (float) (line2Length + paddingKedu * 0.65 + mShaderWidth * 2), paintGapLine); canvas.restore(); canvas.save(); canvas.rotate(0, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, line2Length + paddingKedu * 3, mWidth / 2, (float) (line2Length + paddingKedu * 0.65 + mShaderWidth * 2), paintGapLine); canvas.restore(); canvas.save(); canvas.rotate(-75, mWidth / 2, mWidth / 2); canvas.drawLine(mWidth / 2, line2Length + paddingKedu * 3, mWidth / 2, (float) (line2Length + paddingKedu * 0.65 + mShaderWidth * 2), paintGapLine); canvas.restore(); } /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { Resources r = context.getResources(); float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue, r.getDisplayMetrics()); return (int) px; } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 sp */ public static int px2sp(Context context, float pxValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (pxValue / fontScale + 0.5f); } /** * 根据手机的分辨率从 sp 的单位 转成为 px */ public static int sp2px(Context context, float spValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } }