实现记步样式的进度条

之前看到一种记步进度的条的样式 就想怎么去实现的 然就去动手去实现。

代码如下

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下载:源码地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值