您的位置:首页 > 其它

FanProgressBar,渐变的替代方案

2017-12-19 17:35 267 查看
公司项目想做个渐变效果,最终实现方案

public class FanProgressBar extends View {
/**
* 画笔对象的引用
*/
private Paint circlePaint;  //底部圆环画笔
private Paint arcPaint;  //上部圆弧画笔
private Paint topCirclePoint;  //顶部圆点
private Path mPath;
private boolean capRound;  //画笔形状
private int roundColor;  //圆环的颜色
private int roundProgressColor;  //圆弧进度的颜色
private float roundWidth;  //圆环的宽度
private int maxProgress = 100;  //最大进度
private float progress;  //当前进度
private int style = STROKE;  //进度的风格,实心或者空心
public static final int STROKE = 0;
public static final int FILL = 1;

public FanProgressBar(Context context) {
this(context, null);
}

public FanProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}

public FanProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.FanProgressBar);
// 获取自定义属性和默认值
roundColor = mTypedArray.getColor(R.styleable.FanProgressBar_bgColor, Color.RED);
roundProgressColor = mTypedArray.getColor(R.styleable.FanProgressBar_fgColor, Color.GREEN);
roundWidth = mTypedArray.getDimension(R.styleable.FanProgressBar_fanRoundWidth, DensityUtil.dip2px(getContext(), 15));
progress = mTypedArray.getInt(R.styleable.FanProgressBar_fanProgress, 0);
capRound = mTypedArray.getBoolean(R.styleable.FanProgressBa
4000
r_capRound, true);

mTypedArray.recycle();
}

private RectF mOval;
private SweepGradient sweepGradient;
private List<Integer> colorList = new ArrayList<>();
private static final int[] colors = new int[]{Color.GREEN, Color.GREEN, Color.BLUE, Color.RED, Color.RED};
private float circleSize;

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
float size = Math.min(w, h);
circleSize = size;
mOval = new RectF(roundWidth / 2, roundWidth / 2, size - roundWidth / 2, size - roundWidth / 2);
init();
}

/**
* 初始化操作
*/
private void init() {
circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
circlePaint.setColor(roundColor); // 设置圆环的颜色
circlePaint.setStyle(Paint.Style.STROKE); // 设置空心
circlePaint.setStrokeWidth(roundWidth); // 设置圆环的宽度
circlePaint.setAntiAlias(true); // 消除锯齿
circlePaint.setStrokeCap(capRound ? Paint.Cap.ROUND : Paint.Cap.SQUARE);

int[] colors = new int[colorList.size()];
for (int i = 0; i < colors.length; i++) {
colors[i] = colorList.get(i);
}
sweepGradient = new SweepGradient(mOval.centerX(), mOval.centerY(), colors, null);

arcPaint = new Paint();
//        arcPaint.setColor(roundProgressColor); // 设置圆环的颜色
arcPaint.setStyle(Paint.Style.STROKE); // 设置空心
arcPaint.setStrokeWidth(roundWidth); // 设置圆环的宽度
arcPaint.setAntiAlias(true); // 消除锯齿
arcPaint.setStrokeCap(capRound ? Paint.Cap.ROUND : Paint.Cap.SQUARE);
arcPaint.setShader(sweepGradient);

mPath = new Path();
//        mPath.reset();
//        mPath.addArc(mOval, 30, maxProgress);

topCirclePoint = new Paint();
topCirclePoint.setColor(ContextCompat.getColor(getContext(), R.color.white)); // 设置圆环的颜色
topCirclePoint.setStyle(Paint.Style.FILL_AND_STROKE);
topCirclePoint.setAntiAlias(true); // 消除锯齿
}

/**
* 调用canvas.restore()方法之前必须先调用canvas.save()方法, 不然会报错
* canvas的save 和 restore是成对使用(restore只能比save少,不能多)
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mOval, 0, 360, false, circlePaint); // 画出圆环

//画圆弧, 画圆环的进度
canvas.save();
float perimeter = mOval.width() * (float) Math.PI;  //diameter 直径  radius 半径
float deltaDegree = roundWidth / 2 / perimeter * 360;
//避免由于Paint设置StrokeCap为ROUND而引起的颜色延伸
//        deltaDegree = 30
ee65
;
canvas.rotate(-90 - deltaDegree, circleSize / 2, circleSize / 2);
switch (style) {
case STROKE: {
//                Paint p = new Paint();
//                参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像
//                Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变
//                LinearGradient lg = new LinearGradient(0, 0, 400, 400, colors, positions, Shader.TileMode.MIRROR);
//                arcPaint.setShader(lg);

//                mPath.reset();
//                mPath.addArc(mOval, 30, progress);
//                canvas.drawPath(mPath, arcPaint);
canvas.drawArc(mOval, deltaDegree, progress, false, arcPaint); // 根据进度画圆弧
break;
}
case FILL: {
arcPaint.setStyle(Paint.Style.FILL_AND_STROKE);
if (progress != 0)
canvas.drawArc(mOval, 0, 360 * progress / maxProgress, true, arcPaint); // 根据进度画圆弧
break;
}
}
canvas.restore();
//
//        //保存之后,再旋转回原来的角度,这样白色小圆点就可以显示在圆环顶部了
//        canvas.rotate(90 + deltaDegree, circleSize / 2, circleSize / 2);
canvas.drawCircle(mOval.centerX(), roundWidth / 2, DensityUtil.dip2px(getContext(), 4), topCirclePoint);
}

/**
* 获取进度.需要同步
*/
public synchronized float getProgress() {
return progress;
}

public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
colorList.clear();
for (int color : colors) {
colorList.add(color);
}

//将颜色值按比例分配到360个degree里面,不够的部分填充为其他颜色,反正也是显示不出来的,因为最大进度就那么多
float percent = maxProgress / 360f;
int maxSize = (int) ((colorList.size() / percent) + 0.5);
if (maxSize > colorList.size()) {
for (int i = 0; i < maxSize - colorList.size(); i++) {
colorList.add(Color.YELLOW);
}
}
}

public int getMaxProgress() {
return maxProgress;
}

/**
* 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 刷新界面调用postInvalidate()能在非UI线程刷新
*/
public void setProgress(int progress) {
if (progress < 0) {
progress = 0;
}
if (progress > maxProgress) {
progress = maxProgress;
}
setAnimation(progress);
}

/**
* 为进度设置动画
*/
public void setAnimation(float progress) {
ValueAnimator progressAnimator = ValueAnimator.ofFloat(0, progress);
progressAnimator.setDuration(3000);
progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
FanProgressBar.this.progress = (float) animation.getAnimatedValue();
invalidate();
}
});
progressAnimator.start();
}
}


关键是这部分代码:

public void setMaxProgress(int maxProgress) {
this.maxProgress = maxProgress;
colorList.clear();
for (int color : colors) {
colorList.add(color);
}

//将颜色值按比例分配到360个degree里面,不够的部分填充为其他颜色,反正也是显示不出来的,因为最大进度就那么多
float percent = maxProgress / 360f;
int maxSize = (int) ((colorList.size() / percent) + 0.5);
if (maxSize > colorList.size()) {
for (int i = 0; i < maxSize - colorList.size(); i++) {
colorList.add(Color.YELLOW);
}
}
}


效果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: