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); } } }
效果如图:
相关文章推荐
- 密码存储中MD5的安全问题与替代方案
- iOS5:[UIDevice uniqueIdentifier]的替代方案
- Win8无法获取机器唯一标识的替代方案
- javascript中alert函数的替代方案,一个自定义的对话框的方法(引用)
- Linux 环境下快速部署 MySQL 的替代方案
- jmx rmi 穿越防火墙问题及jmxmp的替代方案
- 替代废除iframe方案
- [Python] Mac OS 下 os.startfile 的替代方案
- 【微服务】分布式事务的实现方法及替代方案
- SQL Server 2012 不支持创建连接服务器到 2000 版本,及其替代方案
- mysql show table status 的替代方案:获得更多更具体的表信息
- OpenSessionInViewFilter 的配置及替代方案
- SSH Secure Shell Client的替代方案
- 006_005 Python 继承的替代方案,自动托管
- javascript中alert函数的替代方案,一个自定义的对话框的方法javascript
- 【转】beancopy的替代方案
- 没有mysql支持时的替代方案
- Effective C++ (E3 35)笔记之替代virtual函数的若干方案
- nw.js(node-webkit) node-serialport的替代方案
- Chrome showModalDialog undefined is not a function 的替代方案