这个就是使用Paint和Canvas一个个画上去的,再加上动画,总体来说不难,就是变量多,所以看起来的时候要慢慢看,现在在这贴下代码
布局文件:
xml version="1.0" encoding="utf-8"?>xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > android:id="@+id/seekbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="10px" android:paddingRight="10px" android:layout_marginTop="20px" /> android:layout_width="300px" android:layout_height="300px" android:layout_marginTop="90px" android:layout_marginLeft="60px" > android:id="@+id/carview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#8B5F65" />
自定义veiw
package com.example.speeddemo; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.util.AttributeSet; import android.view.View; /** * Created by admin on 2016/8/28. */ public class CarRecorderView extends View { private static final String TAG = "CarRecorderView" ; private LinearGradient linearGradient = null; private Paint blackCirclePaint; private int blackCirClePaintWidth = 8; private Paint arcAnimPaint; private Paint outerAnimPaint; private Paint whiteCirclePaint ; private Paint unitTextPaint; private int whiteCirclePaintWidth = 24; private Paint outerPaint; private Paint linePaint; private Paint textValuePaint; private Paint interprogressPaint; private int lineWidth = 5; private Paint outerSmallPaint; private RectF outerRectF; private RectF outerAnimRectF ; private Bitmap carBitmap; private int width; private int height; private int min = 0; private float value; private long duration = 1000; private long progressDelay = 350; private int startAngle = 140;//开始的角度 private float plusAngle = 0;//经过的角度 private float maxAngle = 260f;//最大的角度 private float outerProgressValue = min; private float lineInitValue = min; private int max = 100;//最大进度值 private ValueAnimator lineAnim; private ValueAnimator outerProgressAnim; public CarRecorderView(Context context) { super(context); } public CarRecorderView(Context context, AttributeSet attrs) { super(context, attrs); initPaint(); initAnim(); } private void updateOuterProgressValue(float value) { setOuterAnimAngle(value); } public void setOuterAnimAngle(float value){ this.plusAngle = (maxAngle * value) / max; invalidate(); } private void updateProgressText(float value) { updateValue(value); } /** * 初始化画笔 */ private void initPaint() { arcAnimPaint = new Paint(); arcAnimPaint.setStrokeWidth(12); arcAnimPaint.setColor(Color.parseColor("#1C86EE")); arcAnimPaint.setAntiAlias(true); arcAnimPaint.setStyle(Paint.Style.STROKE); interprogressPaint = new Paint(); interprogressPaint.setStrokeWidth(12); interprogressPaint.setColor(Color.RED); interprogressPaint.setAntiAlias(true); interprogressPaint.setStyle(Paint.Style.STROKE); unitTextPaint = new Paint(); unitTextPaint.setColor(Color.parseColor("#DBDBDB")); unitTextPaint.setTextSize(20); unitTextPaint.setAntiAlias(true); textValuePaint = new Paint(); textValuePaint.setColor(Color.parseColor("#DBDBDB")); textValuePaint.setTextSize(40); textValuePaint.setAntiAlias(true); blackCirclePaint = new Paint(); blackCirclePaint.setColor(Color.parseColor("#1A1A1A")); blackCirclePaint.setStrokeWidth(blackCirClePaintWidth); blackCirclePaint.setStyle(Paint.Style.STROKE); blackCirclePaint.setAntiAlias(true); whiteCirclePaint = new Paint(); whiteCirclePaint.setColor(Color.parseColor("#1A1A1A")); whiteCirclePaint.setStrokeWidth(whiteCirclePaintWidth); whiteCirclePaint.setStyle(Paint.Style.STROKE); whiteCirclePaint.setAntiAlias(true); outerPaint = new Paint(); outerPaint.setColor(Color.parseColor("#080808")); outerPaint.setStrokeWidth(whiteCirclePaintWidth); outerPaint.setStyle(Paint.Style.STROKE); outerPaint.setAntiAlias(true); outerSmallPaint = new Paint(); outerSmallPaint.setColor(Color.RED); outerSmallPaint.setStrokeWidth(whiteCirclePaintWidth-8); outerSmallPaint.setStyle(Paint.Style.STROKE); outerSmallPaint.setAntiAlias(true); linePaint = new Paint(); linePaint.setColor(Color.parseColor("#20B2AA")); linePaint.setStrokeWidth(lineWidth); linePaint.setStyle(Paint.Style.FILL); linePaint.setAntiAlias(true); float[] intervals =new float[]{8,12}; DashPathEffect dashPathEffect = new DashPathEffect(intervals,0); outerPaint.setPathEffect(dashPathEffect); outerAnimPaint = new Paint(); outerAnimPaint.setColor(Color.RED); outerAnimPaint.setPathEffect(dashPathEffect); outerAnimPaint.setStyle(Paint.Style.STROKE); outerAnimPaint.setAntiAlias(true); outerAnimPaint.setStrokeWidth(whiteCirclePaintWidth); carBitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.car1); linearGradient = new LinearGradient(0, 0, 50, 50, new int[] { Color.parseColor("#A4D3EE"), Color.parseColor("#9400D3"), Color.parseColor("#43CD80"), Color.parseColor("#528B8B") }, null, Shader.TileMode.REPEAT); outerPaint.setShader(linearGradient); } public CarRecorderView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); widthSize = heightSize > widthSize ?widthSize:heightSize; heightSize = heightSize > widthSize ?widthSize:heightSize; setMeasuredDimension(widthSize,heightSize); height = width = widthSize; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawCircle(width/2,height/2,width/2,blackCirclePaint); canvas.drawCircle(width/2,height/2,width/2-blackCirClePaintWidth,whiteCirclePaint); canvas.drawBitmap(carBitmap,(width-carBitmap.getWidth())/2,(height-carBitmap.getHeight())/2,blackCirclePaint); float toX = width / 2 + (float) Math.cos(Math.toRadians(plusAngle + startAngle)) * (width/2-whiteCirclePaintWidth-2); float toY = width / 2 + (float) Math.sin(Math.toRadians(plusAngle + startAngle)) * (width/2-whiteCirclePaintWidth-2); canvas.drawLine(width/2, width/2, toX, toY, linePaint); canvas.drawText("kmh",width/2-50+textValuePaint.measureText("100"),height-45,unitTextPaint); canvas.drawText(String.format("%.0f", lineInitValue),width/2-55,height-45,textValuePaint); outerRectF = new RectF(); outerAnimRectF = new RectF(); outerAnimRectF.set(blackCirClePaintWidth-1-1,blackCirClePaintWidth-1-1,width-blackCirClePaintWidth+1+1,height-blackCirClePaintWidth+1+1); outerRectF.set(blackCirClePaintWidth-1-1,blackCirClePaintWidth-1-1,width-blackCirClePaintWidth+1+1,height-blackCirClePaintWidth+1+1); canvas.drawArc(outerRectF,startAngle,maxAngle,false,outerPaint); canvas.drawArc(outerAnimRectF,startAngle,plusAngle,false,outerAnimPaint); RectF rectF = new RectF(60,60,height-60,height-60); canvas.drawArc(rectF,startAngle,maxAngle,false,interprogressPaint); canvas.drawArc(rectF,startAngle,plusAngle,false,arcAnimPaint); } public void updateValue(float value) { this.plusAngle = (maxAngle * value) / max; invalidate(); } public void startAnim(float value) { this.value = value; if (value <= max && value >= min) { updateAnimValue(); } } private void updateAnimValue() { if (lineAnim != null) { outerProgressAnim.setFloatValues(outerProgressValue, value); outerProgressAnim.setDuration(duration + progressDelay); outerProgressAnim.start(); lineAnim.setFloatValues(lineInitValue, value); lineAnim.setDuration(duration); lineAnim.start(); } } /** * 初始化属性动画 */ private void initAnim() { outerProgressAnim = new ValueAnimator(); outerProgressAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); updateOuterProgressValue(value); outerProgressValue = value; } }); lineAnim = new ValueAnimator(); lineAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener(){ @Override public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); updateProgressText(value); lineInitValue = value; } }); } }
使用入口:
package com.example.speeddemo; import android.app.Activity; import android.os.Bundle; import android.widget.SeekBar; public class MainActivity extends Activity { private CarRecorderView carview; private SeekBar seekbar; private int speedValue = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); seekbar = (SeekBar) findViewById(R.id.seekbar); carview = (CarRecorderView) findViewById(R.id.carview); seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){ @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { carview.startAnim(progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); } }效果图:
发现这还有点bug,明天改下