项目需要,需要自定义带渐变色的进度条,效果如下:
canvas.drawRoundRect(mBgRect, mViewHeight / 2, mViewHeight / 2, mBgPaint);
canvas.drawRoundRect(mBgRect, mViewHeight / 2, mViewHeight / 2, mStrokePaint);
//可变矩形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);
//遮罩
mProgressPaint.setXfermode(mXfermode);
mProgressPaint.setShader(mShader);
canvas.drawRect(progressRect, mProgressPaint);
mProgressPaint.setXfermode(null);
//刻度
for (int i = 0; i < mTickNums - 1; i++) {
canvas.drawLine((i + 1) * mMackTickWidth, mStrokeWidth / 2, (i + 1) * mMackTickWidth, mViewHeight - mStrokeWidth / 2, mMackTickPaint);
}
/**
* 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();
}
}