项目需要,需要自定义带渐变色的进度条,效果如下:
文章图片
1,思路
- 首先绘制 roundRect 带半圆的矩形背景
- 绘制一个 可变的rect矩形 ,让rect的宽度不断的变大来实现对下面roundRect覆盖
- 通过PorterDuffXfermode的PorterDuff.Mode.SRC_IN来取可变rect跟背景rect相交的部分
- 记得取消硬件加速
- LinearGradient 渐变色
- PorterDuffXfermode 去交集部分渲染
- 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 = https://www.it610.com/article/(float) animation.getAnimatedValue();
//不断的改变可变矩形的宽度
mProgressWidth = (int) (mAnimatorValue * mViewWidth);
invalidate();
}
};
mAnimator.addUpdateListener(mUpdateListener);
mAnimator.start();
}
【Android|自定义横向带刻度progressbar】这里是一个大概的实现,完整代码。
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 = https://www.it610.com/article/(float) animation.getAnimatedValue();
mProgressWidth = (int) (mAnimatorValue * mViewWidth);
invalidate();
}
};
mAnimator.addUpdateListener(mUpdateListener);
mAnimator.start();
}
}