每周一个自定义View(1) -动态ProgressView
新的一个系列, 应该是计划每周实现一个自定义View, 看看能检查到多久吧
这次就从一个常见的ProgressBark开始吧, 最近的项目中使用了一个Progress显示文件下载进度的功能, 设计给的是一个静态的图片, 也没有说需要具体实现的情况, 后面优化的时候刚好有了性质, 就有了下面的这个AnimatorProgressBar.
效果展示
支持功能
- 基本的的进度设置(当前默认为0-100)
- 颜色定义, 使用的颜色都是可以设置的, 满足各样的ui需求
- 元素定义, 作为展示的Progress中的线条可以设置宽度和间距
- 动画控制, 动画效果可以设置展示速度, 总有一个组合适合你
设计过程
将相关的view分为了四层, 从下至上分别为
- 背景图层
用于显示整个view的背景
- 进度图层
相当于进度条的背景颜色
- 线段动画图层
在这里绘制出现的线段, 并控制器动画的效果
- 遮罩展示图层
这里使用了遮罩展示的方法, 控制遮罩图层的进度和样式来表现实际的展示效果
实现过程
首先是背景如果绘制的, 简单来说就是两个圆形和一个矩形, 具体的动画效果可以参考下面,
其它的图层基本上也都是比较类似的情况, 除此之外就是线条的实现
其中中心黑色的为展示的区域, 白色的是绘制的区域
代码实现
可编辑参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| private int viewBackGroundColor; private int viewLineColor; private int viewProgressColor; private int offsetLine; private int animatorTime; private int animatorProgressTime; private int paintWidth;
|
背景图层&绘制图层背景
这两个图形的实现比较类似
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
private void getProgressBackground(Canvas canvas){ Paint paint = new Paint(); paint.setColor(viewProgressColor);
int leftCirclePoint = height / 2; int rightCirclePoint = width - leftCirclePoint; int radius = height / 2;
canvas.drawCircle(leftCirclePoint, height >> 1, radius, paint); canvas.drawCircle(rightCirclePoint, height >> 1, radius, paint);
Rect rect = new Rect(leftCirclePoint, 0, rightCirclePoint, height); canvas.drawRect(rect, paint); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
private void drawViewBackground(Canvas canvas) { canvas.save();
Paint paint = new Paint(); paint.setColor(viewBackGroundColor);
int leftCirclePoint = height / 2; int rightCirclePoint = width - leftCirclePoint; int radius = height / 2;
canvas.drawCircle(leftCirclePoint, height >> 1, radius, paint); canvas.drawCircle(rightCirclePoint, height >> 1, radius, paint);
Rect rect = new Rect(leftCirclePoint, 0, rightCirclePoint, height); canvas.drawRect(rect, paint); }
|
绘制遮罩图层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
private Bitmap progressBitmapDst(){ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
if (progress == 0){ return bitmap; } Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint(); paint.setColor(Color.WHITE);
int leftCirclePoint = height / 2; int rightCirclePoint = leftCirclePoint + (int) ((width - height) / 1f * progress / 100f);
int radius = height / 2;
canvas.drawCircle(leftCirclePoint, height >> 1, radius, paint); canvas.drawCircle(rightCirclePoint, height >> 1, radius, paint);
Rect rect = new Rect(leftCirclePoint, 0, rightCirclePoint, height); canvas.drawRect(rect, paint);
return bitmap; }
|
绘制线条动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
private void getProgressLines(Canvas canvas){ Paint paint = new Paint(); paint.setColor(viewLineColor);
paint.setStrokeWidth(paintWidth);
paint.setStrokeCap(Paint.Cap.ROUND); canvas.translate(-offsetLine * 2, 0); canvas.translate(offsetAnimator, 0); canvas.save();
int indexOffset = 0;
do { canvas.drawLine(20, -20, -offsetLine - 20, height + 20, paint); indexOffset += offsetLine; canvas.translate(offsetLine, 0); }while (indexOffset < width + offsetLine * 4);
canvas.restore(); } ```
### 动画效果 ```java
public void startProgressAnimator(int startProgress, int endProgress){ ValueAnimator va = ValueAnimator.ofFloat(startProgress, endProgress); va.setDuration(animatorProgressTime); va.setInterpolator(new LinearInterpolator()); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { progress = (float) valueAnimator.getAnimatedValue(); invalidate(); }
});
va.start(); }
public void startAnimator(){ ValueAnimator va = ValueAnimator.ofFloat(0f, offsetLine); va.setRepeatCount(ValueAnimator.INFINITE); va.setDuration(animatorTime); va.setInterpolator(new LinearInterpolator()); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { offsetAnimator = (float) valueAnimator.getAnimatedValue(); invalidate(); } });
va.start(); }
|
最后
相关代码可以访问我的GitHub来获取,欢迎大家start或者提供建议.