自定义横向带刻度progressbar

来源:互联网 发布:2016党章党规网络测试 编辑:程序博客网 时间:2024/05/16 06:34

项目需要,需要自定义带渐变色的进度条,效果如下:

1,思路

  • 首先绘制 roundRect 带半圆的矩形背景
  • 绘制一个 可变的rect矩形 ,让rect的宽度不断的变大来实现对下面roundRect覆盖
  • 通过PorterDuffXfermode的PorterDuff.Mode.SRC_IN来取可变rect跟背景rect相交的部分
  • 记得取消硬件加速

2,用到的主要知识点

  • LinearGradient 渐变色
  • PorterDuffXfermode 去交集部分渲染

3,开始绘制

  • 1,初始化,onsizechange ,onMeasure省略…
  • 2,画背景跟边
  canvas.drawRoundRect(mBgRect, mViewHeight / 2, mViewHeight / 2, mBgPaint);  canvas.drawRoundRect(mBgRect, mViewHeight / 2, mViewHeight / 2, mStrokePaint);
  • 3,初始化可变的rect矩形跟渐变色的shader
    //可变矩形mProgressWidth  RectF progressRect = new RectF(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth - mStrokeWidth / 2, mViewHeight - mStrokeWidth / 2);    //渐变色的起始x,y;终点x,y;渐变色的开始,终止颜色,模式 Shader mShader = new LinearGradient(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth, mHeight - mStrokeWidth / 2, Color.parseColor("#27a6ff"), Color.parseColor("#099aff"), Shader.TileMode.REPEAT);
  • 4,绘制这个遮罩的rect
  //遮罩        mProgressPaint.setXfermode(mXfermode);        mProgressPaint.setShader(mShader);        canvas.drawRect(progressRect, mProgressPaint);    mProgressPaint.setXfermode(null);
  • 5,绘制刻度
//刻度        for (int i = 0; i < mTickNums - 1; i++) {            canvas.drawLine((i + 1) * mMackTickWidth, mStrokeWidth / 2, (i + 1) * mMackTickWidth, mViewHeight - mStrokeWidth / 2, mMackTickPaint);        }  
  • 6,提供对外方法
    /**     * progress取值范围[0-1]     */    public void setProgress(float progress) {        if (progress < 0) {            progress = 0;        } else if (progress > 1) {            progress = 1;        }        int delta = (int) (progress / 0.1);        delta = delta == 0 ? 1 : delta;        mAnimator = ValueAnimator.ofFloat(0, progress).setDuration(delta * DURATION);        mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mAnimatorValue = (float) animation.getAnimatedValue();                //不断的改变可变矩形的宽度                mProgressWidth = (int) (mAnimatorValue * mViewWidth);                invalidate();            }        };        mAnimator.addUpdateListener(mUpdateListener);        mAnimator.start();    }

这里是一个大概的实现,完整代码。

public class TickProgress extends View {    private static final long DURATION = 200;    private int mViewWidth;    private int mViewHeight;    private int mStrokeWidth;    private int mProgressWidth;    private Paint mBgPaint;    private Paint mProgressPaint;    private Paint mMackTickPaint;    private int mStrokeColor = Color.parseColor("#a3daff");    private ValueAnimator.AnimatorUpdateListener mUpdateListener;    private ValueAnimator mAnimator;    // 动画数值(用于控制动画状态,因为同一时间内只允许有一种状态出现,具体数值处理取决于当前状态)    private float mAnimatorValue;    public TickProgress(Context context) {        this(context, null);    }    public TickProgress(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    private Paint mStrokePaint;    private int mHeight;    public TickProgress(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        mHeight = DisplayUtil.dip2px(context, 10);        mStrokeWidth = DisplayUtil.dip2px(context, 1);        mBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mBgPaint.setStyle(Paint.Style.FILL);        mBgPaint.setStrokeWidth(mHeight);        mBgPaint.setColor(Color.parseColor("#e6f6ff"));        mStrokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mStrokePaint.setStyle(Paint.Style.STROKE);        mStrokePaint.setStrokeWidth(mStrokeWidth);        mStrokePaint.setColor(mStrokeColor);        mProgressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mProgressPaint.setStrokeWidth(mHeight);        mProgressPaint.setStyle(Paint.Style.FILL);        mMackTickPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mMackTickPaint.setStyle(Paint.Style.STROKE);        mMackTickPaint.setStrokeWidth(mStrokeWidth);        mMackTickPaint.setColor(mStrokeColor);        setLayerType(LAYER_TYPE_HARDWARE, null);    }    private int mMackTickWidth;    @Override    protected void onSizeChanged(int w, int h, int oldw, int oldh) {        super.onSizeChanged(w, h, oldw, oldh);        mViewHeight = h;        mViewWidth = w;        mMackTickWidth = w / 10;    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(widthMeasureSpec, mHeight);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        RectF rectF2 = new RectF(mStrokeWidth, mStrokeWidth, mViewWidth - mStrokeWidth, mHeight - mStrokeWidth);        canvas.drawRoundRect(rectF2, mHeight / 2, mHeight / 2, mBgPaint);        canvas.drawRoundRect(rectF2, mHeight / 2, mHeight / 2, mStrokePaint);        RectF rectF1 = new RectF(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth - mStrokeWidth / 2, mViewHeight - mStrokeWidth / 2);        Path path = new Path();        Path dstPath = new Path();        PathMeasure pathMeasure = new PathMeasure();        path.moveTo(0, 0);        path.lineTo(mViewWidth, 0);        pathMeasure.setPath(path, false);        pathMeasure.getSegment(0, pathMeasure.getLength() * mAnimatorValue, dstPath, true);        //渐变        Shader mShader = new LinearGradient(mStrokeWidth / 2, mStrokeWidth / 2, mProgressWidth, mHeight - mStrokeWidth / 2, Color.parseColor("#27a6ff"), Color.parseColor("#099aff"), Shader.TileMode.REPEAT);        //遮罩        mProgressPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));        mProgressPaint.setShader(mShader);        canvas.drawRect(rectF1, mProgressPaint);        mProgressPaint.setXfermode(null);        //刻度        for (int i = 0; i < 9; i++) {            canvas.drawLine((i + 1) * mMackTickWidth, mStrokeWidth / 2, (i + 1) * mMackTickWidth, mViewHeight - mStrokeWidth / 2, mMackTickPaint);        }    }    /**     * 0--1     */    public void setProgress(float progress) {        if (progress < 0) {            progress = 0;        } else if (progress > 1) {            progress = 1;        }        int delta = (int) (progress /0.1);        LogUtils.d("delta:"+delta);        delta = delta == 0 ? 1 : delta;        mProgressWidth = (int) (progress * mViewWidth);        mAnimator = ValueAnimator.ofFloat(0, progress).setDuration(delta * DURATION);        mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator animation) {                mAnimatorValue = (float) animation.getAnimatedValue();                mProgressWidth = (int) (mAnimatorValue * mViewWidth);                invalidate();            }        };        mAnimator.addUpdateListener(mUpdateListener);        mAnimator.start();    }}
0 0
原创粉丝点击