Android自定义仪表盘 并实现动画

packagecom.yuntong.tv.view;

importandroid.animation.ValueAnimator;

importandroid.content.Context;

importandroid.content.res.TypedArray;

importandroid.graphics.Bitmap;

importandroid.graphics.BitmapFactory;

importandroid.graphics.Canvas;

importandroid.graphics.Color;

importandroid.graphics.Paint;

importandroid.graphics.PaintFlagsDrawFilter;

import android.graphics.RectF;

importandroid.os.Handler;

importandroid.os.Message;

importandroid.text.TextUtils;

importandroid.util.AttributeSet;

importandroid.view.View;

importandroid.view.animation.AccelerateDecelerateInterpolator;

importandroid.view.animation.LinearInterpolator;

importcom.yuntong.tv.R;

/**

* Created by ctdw on 2017/1/10.

*/

public classYiBiaoPanViewNewextendsView {

privateContextcontext;

//刻度的结束位置

private intendDst;

//刻度的开始位置

private intstartDst;

//外环图片

privateBitmapmBitmapOutRing;

//光标图片

privateBitmapmBitmapGuangBiao;

//外环底部图片

privateBitmapmBitmapOutDoor;

//当前的刻度

private intmPerent;

//View的宽

private intmWidth;

//View的高

private intmHeight;

//总刻度的颜色

private inttotalKeDuColor;

//当前刻度的颜色

private intcurrentKeDuColor;

//最外层图片圆环和底部图片的画笔宽度

private intoutPaintWidth;

//画刻度的画笔宽度

private intkeduPaintWidth;

privatePaintFlagsDrawFiltermPaintFlagsDrawFilter;

//外层圆环和底部图片画笔

privatePaintmBitmapOutRingAndOutDoorPaint;

//总刻度的画笔

privatePaintmTotalKeduPaint;

//当前刻度的画笔

privatePaintmCurrentKeduPaint;

//最外层圆环图片的矩阵

privateRectFmBitmapOutRingRectf;

//底部图片的矩阵

privateRectFmBitmapOutDoorRecft;

private intmBitmapOutRingWidth;

private intmBitmapOutRingHeight;

private intmBitmapOutDoorWidth;

private intmBitmapOutDoorHeight;

//文本的画笔

privatePaintmCenterTextPaint;

//最上层文本的颜色

private static final intWHITE_COLOR= Color.parseColor("#ffffff");

//底部文本颜色

private static final intBLACK_COLOR= Color.parseColor("#000000");

//室内PM2.5

privateStringmPmText;

privateStringmPmTextNumber;

privateStringmPmTextLevel;

privateStringmPmTextOut;

private intcurrentKeDuColorDi;

private intmMaxNum=1000;

private intmMinNum=0;

private intmMinNumOut=0;

private intmPerents=0;

privateRectFmBitmapGuangBiaoRectf;

private intmBitmapGuangBiaoWidth;

private intmBitmapGuangBiaoHeight;

private float[]pos;

private float[]tan;

privateRectFmMiddleProgressRect;

private floatmStartAngle=139f;

private floatmCurrentAngle=0f;

privatePaintmArcProgressPaint;

private floatmTotalAngle;

privatePaintmCenterTextPaints;

privatePaintmCenterTextPaints1;

privateStringmUnitPM25="";

publicYiBiaoPanViewNew(Context context) {

this(context, null);

}

publicYiBiaoPanViewNew(Context context,AttributeSet attrs) {

this(context,attrs,0);

}

private static final intDATA_CHANGED=0;

booleanisHint=true;

HandlermHandler=newHandler() {

@Override

public voidhandleMessage(Message msg) {

switch(msg.what) {

caseDATA_CHANGED:

isHint= !isHint;

postInvalidate();

break;

}

}

};

RunnablemRunnable=newRunnable() {

@Override

public voidrun() {

mHandler.postDelayed(mRunnable,1000);

Message message =newMessage();

message.what=DATA_CHANGED;

mHandler.sendMessage(message);

}

};

publicYiBiaoPanViewNew(Context context,AttributeSet attrs, intdefStyleAttr) {

super(context,attrs,defStyleAttr);

this.context= context;

TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.PanelView);

totalKeDuColor= typedArray.getColor(R.styleable.PanelView_keduColor,Color.parseColor("#365275"));

//        currentKeDuColor = typedArray.getColor(R.styleable.PanelView_arcColor, Color.parseColor("#14B8D4"));

outPaintWidth= typedArray.getDimensionPixelSize(R.styleable.PanelView_outPaintWidth,5);

keduPaintWidth= typedArray.getDimensionPixelSize(R.styleable.PanelView_keduPaintWidth,3);

startDst= typedArray.getDimensionPixelOffset(R.styleable.PanelView_startDst,22);

endDst= typedArray.getDimensionPixelOffset(R.styleable.PanelView_endDst,45);

//初始化画笔

init();

mHandler.post(mRunnable);

}

/**

*初始化画笔

*/

private voidinit() {

//设置图片线条的抗锯齿

mPaintFlagsDrawFilter=newPaintFlagsDrawFilter

(0,Paint.ANTI_ALIAS_FLAG| Paint.FILTER_BITMAP_FLAG);

//外层圆环和底部图片画笔

mBitmapOutRingAndOutDoorPaint=newPaint();

mBitmapOutRingAndOutDoorPaint.setStyle(Paint.Style.STROKE);

mBitmapOutRingAndOutDoorPaint.setStrokeWidth(outPaintWidth);

//总刻度的画笔

mTotalKeduPaint=newPaint();

mTotalKeduPaint.setStyle(Paint.Style.STROKE);

mTotalKeduPaint.setStrokeWidth(keduPaintWidth);

mTotalKeduPaint.setColor(totalKeDuColor);

//当前刻度的画笔

mCurrentKeduPaint=newPaint();

mCurrentKeduPaint.setStyle(Paint.Style.STROKE);

mCurrentKeduPaint.setStrokeWidth(keduPaintWidth);

//文本画笔

mCenterTextPaint=newPaint();

mCenterTextPaint.setTextAlign(Paint.Align.CENTER);

mCenterTextPaints=newPaint();

mCenterTextPaints.setTextAlign(Paint.Align.RIGHT);

mCenterTextPaints1=newPaint();

mCenterTextPaints1.setTextAlign(Paint.Align.LEFT);

mArcProgressPaint=newPaint(Paint.ANTI_ALIAS_FLAG);

mArcProgressPaint.setStrokeWidth(1);

mArcProgressPaint.setColor(Color.TRANSPARENT);

mArcProgressPaint.setStyle(Paint.Style.STROKE);

mArcProgressPaint.setStrokeCap(Paint.Cap.ROUND);

}

/**

*测量控件的宽和高

*

*@paramwidthMeasureSpec

*@paramheightMeasureSpec

*/

@Override

protected voidonMeasure(intwidthMeasureSpec, intheightMeasureSpec) {

intwidthSize = MeasureSpec.getSize(widthMeasureSpec);

intwidthMode = MeasureSpec.getMode(widthMeasureSpec);

intheightSize = MeasureSpec.getSize(heightMeasureSpec);

intheightMode = MeasureSpec.getMode(heightMeasureSpec);

if(widthMode == MeasureSpec.EXACTLY) {

mWidth= widthSize;

}else{

mWidth=477;

}

if(heightMode == MeasureSpec.EXACTLY) {

mHeight= heightSize;

}else{

mHeight=477;

}

setMeasuredDimension(mWidth,mHeight);

}

@Override

protected voidonDraw(Canvas canvas) {

//设置画布绘图无锯齿

canvas.setDrawFilter(mPaintFlagsDrawFilter);

//画圆环和底部图片

drawBitmapOutRingAndDoor(canvas);

//画文本文字

drawCenterText(canvas);

//画总刻度

drawTotalKedu(canvas);

//画当前刻度

drawCurrentKedu(canvas);

drawGuangBiao(canvas);

}

/**

*画文本文字

*

*@paramcanvas

*/

private voiddrawCenterText(Canvas canvas) {

//绘制最上边文本

mCenterTextPaint.setTextSize(36);

mCenterTextPaint.setColor(WHITE_COLOR);

canvas.drawText(mPmText,mWidth/2,outPaintWidth+114,mCenterTextPaint);

String mMinNums =mMinNum+"";

//绘制中间文本

mCenterTextPaints.setTextSize(120);

mCenterTextPaints.setColor(WHITE_COLOR);

mCenterTextPaints1.setTextSize(40);

mCenterTextPaints1.setColor(WHITE_COLOR);

intnum;

intdanwei;

if(mMinNums.length() ==4){

mCenterTextPaints.setTextSize(100);

num =40;

danwei =50;

}else{

num =30;

danwei =50;

}

canvas.drawText(mPmTextNumber,mWidth/2+ num,outPaintWidth+250,mCenterTextPaints);

canvas.drawText(mUnitPM25,mWidth/2+ danwei,outPaintWidth+250,mCenterTextPaints1);

//绘制下边文本

mCenterTextPaint.setTextSize(35);

mCenterTextPaint.setColor(WHITE_COLOR);

canvas.drawText(mPmTextLevel,mWidth/2,mHeight-88-outPaintWidth,mCenterTextPaint);

mCenterTextPaint.setTextSize(40);

mCenterTextPaint.setColor(WHITE_COLOR);

canvas.drawText(mPmTextOut,mWidth/2,mHeight-18,mCenterTextPaint);

}

/**

*画当前刻度

*

*@paramcanvas

*/

private voiddrawCurrentKedu(Canvas canvas) {

mCurrentKeduPaint.setColor(currentKeDuColor);

if(mPerent==0) {

//旋转画布

canvas.save();

canvas.rotate(-139f,mWidth/2,mWidth/2);

//旋转的角度

floatrAngle = (280.9f/100);

for(inti =1;i <=0;i++) {

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mCurrentKeduPaint);

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

canvas.restore();

}else if(mPerent==100) {

//旋转画布

canvas.save();

//旋转的角度

floatrAngle = (280.9f/100);

canvas.rotate(-139,mWidth/2,mWidth/2);

for(inti =1;i <=100;i++) {

if(i ==100) {

if(isHint) {

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mCurrentKeduPaint);

}

}

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

canvas.restore();

//旋转画布

canvas.save();

//旋转的角度

floatrAngles = (280.9f/100);

canvas.rotate(-139,mWidth/2,mWidth/2);

for(inti =1;i <100;i++) {

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mCurrentKeduPaint);

canvas.rotate(rAngles,mWidth/2,mWidth/2);

}

canvas.restore();

}else{

//旋转画布

canvas.save();

//旋转的角度

floatrAngle = (280.9f/100);

canvas.rotate(-139,mWidth/2,mWidth/2);

for(inti =1;i <=mPerents;i++) {

if(i ==mPerents) {

if(isHint) {

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mCurrentKeduPaint);

}

}

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

canvas.restore();

//旋转画布

canvas.save();

//旋转的角度

floatrAngles = (280.9f/100);

canvas.rotate(-139,mWidth/2,mWidth/2);

for(inti =1;i

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mCurrentKeduPaint);

canvas.rotate(rAngles,mWidth/2,mWidth/2);

}

canvas.restore();

}

}

private voiddrawGuangBiao(Canvas canvas) {

mCurrentKeduPaint.setColor(currentKeDuColor);

//光标的矩阵

mBitmapGuangBiaoRectf=newRectF((mWidth-mBitmapGuangBiaoWidth) /2,outPaintWidth/2+ dp2px(3f),(mWidth-mBitmapGuangBiaoWidth) /2+mBitmapGuangBiaoWidth,outPaintWidth/2+ dp2px(3f) +mBitmapGuangBiaoHeight);

if(mPerents==0) {

//旋转画布

canvas.save();

canvas.rotate(-139f,mWidth/2,mWidth/2);

//旋转的角度

floatrAngle = (280.9f/100);

for(inti =1;i <=0;i++) {

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

if(isHint) {

canvas.drawBitmap(mBitmapGuangBiao, null,mBitmapGuangBiaoRectf,mCurrentKeduPaint);

}

canvas.restore();

}else if(mPerents==100) {

//旋转画布

canvas.save();

canvas.rotate(-139f,mWidth/2,mWidth/2);

//旋转的角度

floatrAngle = (280.9f/100);

for(inti =2;i <=mPerents;i++) {

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

if(isHint) {

canvas.drawBitmap(mBitmapGuangBiao, null,mBitmapGuangBiaoRectf,mCurrentKeduPaint);

}

canvas.restore();

}else{

//旋转画布

canvas.save();

//旋转的角度

floatrAngle = (280.9f/100);

canvas.rotate(-139,mWidth/2,mWidth/2);

for(inti =2;i <=mPerents;i++) {

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

if(isHint) {

canvas.drawBitmap(mBitmapGuangBiao, null,mBitmapGuangBiaoRectf,mCurrentKeduPaint);

}

canvas.restore();

}

}

/**

*画总刻度

*

*@paramcanvas

*/

private voiddrawTotalKedu(Canvas canvas) {

canvas.save();

canvas.rotate(139f,mWidth/2,mWidth/2);

//旋转的角度

floatrAngle = -280.9f/100;

for(inti =1;i <=100;i++) {

canvas.drawLine(mWidth/2,startDst,mWidth/2,endDst,mTotalKeduPaint);

canvas.rotate(rAngle,mWidth/2,mWidth/2);

}

canvas.restore();

}

/**

*画圆环和底部图片

*

*@paramcanvas

*/

private voiddrawBitmapOutRingAndDoor(Canvas canvas) {

mBitmapOutRingAndOutDoorPaint.setColor(currentKeDuColorDi);

//最外层圆环图片的矩阵

mBitmapOutRingRectf=newRectF(outPaintWidth/2,outPaintWidth/2,mWidth-outPaintWidth/2,mHeight-outPaintWidth/2);

//底部图片的矩阵

mBitmapOutDoorRecft=newRectF((mWidth-mBitmapOutDoorWidth-outPaintWidth) /2+3,mHeight-mBitmapOutDoorHeight-outPaintWidth/2+2,(mWidth-mBitmapOutDoorWidth) /2+mBitmapOutDoorWidth+outPaintWidth/2-2,mHeight);

canvas.drawBitmap(mBitmapOutDoor, null,mBitmapOutDoorRecft,mBitmapOutRingAndOutDoorPaint);

mBitmapOutRingAndOutDoorPaint.setColor(currentKeDuColor);

canvas.drawBitmap(mBitmapOutRing, null,mBitmapOutRingRectf,mBitmapOutRingAndOutDoorPaint);

}

/**

*设置当前PM25的值

*@paramnumber

*@paramnumOut

*@paramvalues

*@parami

*@paramunitPM25

*/

public voidsetCurrentPM25Values(intnumber,String numOut,String values, inti,String unitPM25) {

intnumberOut;

if(TextUtils.equals("",numOut)) {

numberOut =0;

}else{

numberOut = Integer.parseInt(numOut);

}

if(i <=35&& i >=0) {

//空气质量优

mPerent= number;

mPmTextLevel="空气质量优";

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree1);

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon1);

currentKeDuColor= Color.parseColor("#5dca7e");

currentKeDuColorDi= Color.parseColor("#5dca7e");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg1);

}else if(i >35&& i <=75) {

//空气质量良

mPmTextLevel="空气质量良";

mPerent= number;

currentKeDuColor= Color.parseColor("#a6d062");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon2);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree2);

currentKeDuColorDi= Color.parseColor("#a6d062");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg2);

}else if(i >75&& i <=115) {

//轻度污染

mPerent= number;

mPmTextLevel="轻度污染";

currentKeDuColor= Color.parseColor("#f9cf61");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon3);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree3);

currentKeDuColorDi= Color.parseColor("#f9cf61");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg3);

}else if(i >115&& i <=150) {

//中度污染

mPerent= number;

mPmTextLevel="中度污染";

currentKeDuColor= Color.parseColor("#fcb161");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon4);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree4);

currentKeDuColorDi= Color.parseColor("#fcb161");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg4);

}else if(i >150&& i <=250) {

//重度污染

mPerent= number;

mPmTextLevel="重度污染";

mTotalAngle= number *280.9f/100;

currentKeDuColor= Color.parseColor("#ef855b");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon5);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree5);

currentKeDuColorDi= Color.parseColor("#ef855b");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg5);

}else if(i >250&& i <=1000) {

//严重污染

mPerent= number;

mPmTextLevel="严重污染";

mTotalAngle=280.9f;

currentKeDuColor= Color.parseColor("#ed6160");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon6);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree6);

currentKeDuColorDi= Color.parseColor("#ed6160");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg6);

}else{

//严重污染

mPerent=100;

mPmTextLevel="严重污染";

mTotalAngle=280.9f;

currentKeDuColor= Color.parseColor("#ed6160");

mBitmapGuangBiao= BitmapFactory.decodeResource(getResources(),R.drawable.cursor_icon6);

mBitmapOutRing= BitmapFactory.decodeResource(getResources(),R.drawable.pollution_degree6);

currentKeDuColorDi= Color.parseColor("#ed6160");

mBitmapOutDoor= BitmapFactory.decodeResource(getResources(),R.drawable.outdoor_data_bg6);

}

this.mUnitPM25= unitPM25;

mPmText="室内PM2.5";

mPmTextNumber= values;

mPmTextOut="室外:"+ numOut;

mBitmapOutRingWidth=mBitmapOutRing.getWidth();

mBitmapOutRingHeight=mBitmapOutRing.getHeight();

mBitmapGuangBiaoWidth=px2dip(context,mBitmapGuangBiao.getWidth());

mBitmapGuangBiaoHeight=px2dip(context,mBitmapGuangBiao.getHeight());

mBitmapOutDoorWidth=px2dip(context,mBitmapOutDoor.getWidth());

mBitmapOutDoorHeight=px2dip(context,mBitmapOutDoor.getHeight());

startRotateAnim(number,values,numOut,mTotalAngle);

}

/**

*开始刻度绘制动画和数字的改变 和文字的改变

*/

private voidstartRotateAnim(intnum,String values,String numOut, floattotalAngle) {

ValueAnimator mAngleAnim = ValueAnimator.ofFloat(mCurrentAngle,totalAngle);

mAngleAnim.setInterpolator(newAccelerateDecelerateInterpolator());

mAngleAnim.setDuration(2000);

mAngleAnim.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Override

public voidonAnimationUpdate(ValueAnimator valueAnimator) {

mCurrentAngle= (float) valueAnimator.getAnimatedValue();

postInvalidate();

}

});

mAngleAnim.start();

ValueAnimator keduAnim = ValueAnimator.ofInt(mPerents,num);

keduAnim.setInterpolator(newAccelerateDecelerateInterpolator());

keduAnim.setDuration(2000);

keduAnim.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Override

public voidonAnimationUpdate(ValueAnimator animation) {

mPerents= (int) animation.getAnimatedValue();

postInvalidate();

}

});

keduAnim.start();

ValueAnimator mNumAnim = ValueAnimator.ofInt(mMinNum,Integer.parseInt(values));

mNumAnim.setDuration(2000);

mNumAnim.setInterpolator(newLinearInterpolator());

mNumAnim.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Override

public voidonAnimationUpdate(ValueAnimator valueAnimator) {

mMinNum= (int) valueAnimator.getAnimatedValue();

postInvalidate();

}

});

mNumAnim.start();

ValueAnimator mNumAnimOut = ValueAnimator.ofInt(mMinNumOut,Integer.parseInt(numOut));

mNumAnimOut.setDuration(2000);

mNumAnimOut.setInterpolator(newLinearInterpolator());

mNumAnimOut.addUpdateListener(newValueAnimator.AnimatorUpdateListener() {

@Override

public voidonAnimationUpdate(ValueAnimator valueAnimator) {

mMinNumOut= (int) valueAnimator.getAnimatedValue();

postInvalidate();

}

});

mNumAnimOut.start();

}

/**

* dp2px

*/

public intdp2px(floatvalues) {

floatdensity = getResources().getDisplayMetrics().density;

return(int) (values * density +0.5f);

}

public static intpx2dip(Context context, intpxValue) {

floatscale = context.getResources().getDisplayMetrics().density;

return(int) (pxValue / scale +0.5f);

}

}



附上自定义属性


Android自定义仪表盘 并实现动画_第1张图片


Android自定义仪表盘 并实现动画_第2张图片


最后附上效果图:



Android自定义仪表盘 并实现动画_第3张图片

你可能感兴趣的:(Android自定义仪表盘 并实现动画)