之前看到一种记步进度的条的样式 就想怎么去实现的 然就去动手去实现。
代码如下
package com.zyf.customview.view;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import com.zyf.customview.R;
/**
* 作者:小飞
* 创建于 2018年4月16日 17:38:31
*/
public class CustomView extends View {
/**
* 画笔
* */
private Paint mPaint;
/**
* 文字画笔
* */
private Paint mTextPaint;
/**
* 文字画笔
* */
private Paint mSmallTextPaint;
/**
* 填充进度颜色
* */
private int insideColor;
/**
* 背景颜色
* */
private int outsideColor;
/**
* 文字颜色
* */
private int textColor;
/**
* 宽
* */
private int width;
/**
* 高
* */
private int height;
/**
* 当前进度条
* */
private int currentProgress;
/**
* 进度的百分比
* */
private int progress;
/**
* 文字的高度
* */
private int textheight;
/**
* 步数
* */
private int steps;
/**
* 最大步数
* */
private int stepsCount = 5000;
/**
* 单位
* */
private String company;
/**
* 弧线的宽度
* */
private int arcStrokeWidth;
/**
* 进度监听
* */
private OnViewProgressListener listener;
public CustomView(Context context) {
this(context,null);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ty = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView,0,0);
try {
insideColor = ty.getColor(R.styleable.CustomView_inside_color,0xFF40B3FF);
outsideColor = ty.getColor(R.styleable.CustomView_outside_color,0xFF737171);
textColor = ty.getColor(R.styleable.CustomView_text_color,0xFF40B3FF);
steps = ty.getInt(R.styleable.CustomView_step,0);
stepsCount = ty.getInt(R.styleable.CustomView_step_count,5000);
company = ty.getString(R.styleable.CustomView_company);
arcStrokeWidth = ty.getInt(R.styleable.CustomView_arc_stroke_width,20);
if(TextUtils.isEmpty(company)){
company = "步";
}
}finally {
ty.recycle();
}
init();
}
/**
* 初始化属性
* <attr name="inside_color" format="color"></attr>
* <attr name="outside_color" format="color"></attr>
* <attr name="text_color" format="color"></attr>
* */
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(100);
mTextPaint.setColor(textColor);
textheight = (int)(mTextPaint.ascent()+mTextPaint.descent());
mSmallTextPaint = new Paint();
mSmallTextPaint.setAntiAlias(true);
mSmallTextPaint.setTextSize(50);
mSmallTextPaint.setColor(textColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
width = measureSize(widthMeasureSpec);
height = measureSize(heightMeasureSpec);
setMeasuredDimension(width,height);
}
private int measureSize(int measureSpec) {
int length;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if(mode == MeasureSpec.EXACTLY){
length = size;
}else{
length = 500;
if(mode == MeasureSpec.AT_MOST){
length = Math.min(length,size);
}
}
return length;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(listener!=null){
listener.onProgress(currentProgress);
}
//drawInsideStartAndEnd(canvas);
drawInside(canvas);
//drawStartAndEnd(canvas,currentProgress);
drawOutside(canvas,currentProgress);
drawText(canvas,currentProgress);
}
/**
* 画字
* */
private void drawText(Canvas canvas,int steps) {
String str = steps+"";
//线性渐变色 无用
/*LinearGradient lg = new LinearGradient(0,0,width,height,new int[]{0xFFFF4340,0xFFFFE940,0xFF43FF40},null, Shader.TileMode.MIRROR);
mTextPaint.setShader(lg);
mSmallTextPaint.setShader(lg);*/
int textWidth = (int)mTextPaint.measureText(str);
int textsWidth = (int)mSmallTextPaint.measureText(company);
int countWidth = textsWidth +textWidth;
canvas.drawText(str,0,str.length(),(width-countWidth)/2,(height-textheight)/2,mTextPaint);
canvas.drawText(company,0,1,(width+textWidth-textsWidth)/2,(height-textheight)/2,mSmallTextPaint);
}
/**
* 画背景
* */
private void drawInside(Canvas canvas) {
mPaint.setColor(outsideColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(arcStrokeWidth);
RectF rectF = new RectF(arcStrokeWidth,arcStrokeWidth,width-arcStrokeWidth,height-arcStrokeWidth);
canvas.drawArc(rectF,135f,270f,false,mPaint);
}
/**
* 画进度
* */
private void drawOutside(Canvas canvas,int progress) {
float angle;
if((progress/(stepsCount*1f))*270>270){
angle = 270;
}else {
angle = (progress/(stepsCount*1f))*270;
}
mPaint.setColor(insideColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(arcStrokeWidth);
RectF rectF = new RectF(arcStrokeWidth,arcStrokeWidth,width-arcStrokeWidth,height-arcStrokeWidth);
canvas.drawArc(rectF,135f,angle,false,mPaint);
}
/**
* 画开始结束背景 这个方法无用可删除 就是记录自己在不知道api 的情况下画圆上的点的方法
* */
private void drawInsideStartAndEnd(Canvas canvas) {
mPaint.setColor(outsideColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(arcStrokeWidth);
/**
* 圆点坐标:(x0,y0)
* 半径:r
* 角度:a0
*
* 则圆上任一点为:(x1,y1)
* x1 = x0 + r * cos(ao * 3.14 /180 )
* y1 = y0 + r * sin(ao * 3.14 /180 )
* */
canvas.drawCircle((float) (width/2 + (width/2-arcStrokeWidth) * Math.cos(135f*Math.PI/180)),(float) (height/2 + (width/2-arcStrokeWidth) * Math.sin(135f*Math.PI/180)),arcStrokeWidth/2,mPaint);
canvas.drawCircle((float) (width/2 + (width/2-arcStrokeWidth) * Math.cos((135f+270f)*Math.PI/180)),(float) (height/2 + (width/2-arcStrokeWidth) * Math.sin(135f*Math.PI/180)),arcStrokeWidth/2,mPaint);
}
/**
* 画开始结束背景 这个方法无用可删除 就是记录自己在不知道api 的情况下画圆上的点的方法
* */
private void drawStartAndEnd(Canvas canvas,int progress) {
if(progress==0){
return;
}
mPaint.setColor(insideColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(arcStrokeWidth);
//sin45度乘于半径
if(progress<stepsCount){
canvas.drawCircle((float) (width/2 + (width/2-arcStrokeWidth) * Math.cos(135f*Math.PI/180)),(float) (height/2 + (width/2-arcStrokeWidth) * Math.sin(135f*Math.PI/180)),arcStrokeWidth/2,mPaint);
}else {
canvas.drawCircle((float) (width/2 + (width/2-arcStrokeWidth) * Math.cos(135f*Math.PI/180)),(float) (height/2 + (width/2-arcStrokeWidth) * Math.sin(135f*Math.PI/180)),arcStrokeWidth/2,mPaint);
canvas.drawCircle((float) (width/2 + (width/2-arcStrokeWidth) * Math.cos((135f+270f)*Math.PI/180)),(float) (height/2 + (width/2-arcStrokeWidth) * Math.sin(135f*Math.PI/180)),arcStrokeWidth/2,mPaint);
}
float angle;
if((progress/(stepsCount*1f))*270>270){
angle = 270;
}else {
angle = (progress/(stepsCount*1f))*270;
}
float x = (float)(width/2 + (width/2-arcStrokeWidth) * Math.cos((135f+angle)*Math.PI/180));
float y = (float)(height/2 + (width/2-arcStrokeWidth) * Math.sin((135f+angle)*Math.PI/180));
canvas.drawCircle(x,y,arcStrokeWidth/2,mPaint);
}
/**
* 设置初始化进度
* */
/*
public void setProgress(int progress) {
this.progress = progress;
animatorMethod();
}*/
/**
* 设置当前进度
* */
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress;
invalidate();
}
/**
* 属性动画
* */
ValueAnimator anim;
private void animatorMethod(){
if(anim!=null&&anim.isRunning()){
return;
}
anim = ValueAnimator.ofInt(0,steps);
anim.setDuration(3000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
currentProgress = (int)animation.getAnimatedValue();
invalidate();
}
});
anim.start();
}
public void setSteps(int steps) {
this.steps = steps;
animatorMethod();
}
/**
* 设置线条宽度
* */
public void setArcStrokeWidth(int arcStrokeWidth) {
if(arcStrokeWidth<10){
return;
}
this.arcStrokeWidth = arcStrokeWidth;
invalidate();
}
public interface OnViewProgressListener{
void onProgress(int progress);
}
/**
* 设置监听
* */
public void setListener(OnViewProgressListener listener) {
this.listener = listener;
}
}
注释完整。 基本都可以看懂。
demo下载:源码地址