自定义进度条PictureProgressBar——从开发到开源发布全过程
出处:
炎之铠邮箱:yanzhikai_yjk@qq.com
本文原创,转载请注明本出处!
本项目JCenter地址:https://bintray.com/yanzhikaijky/CustomViewRepository/PictureProgressbar/
本项目GitHub地址:https://github.com/totond/PictureProgressBar
欢迎 Star or Fork和在Issue里提出意见建议!
*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
前言
上一篇文章掌握了ProgressBar的自定义样式和它的扩展ProgressDialog,但是没有进行封装,这一次就继承View从零开始做了一个自定义进度条——PictureProgressBar,并发布到Github和JCenter上,下面就开始一步一步介绍这个过程。
PS:JCenter是一个Android的代码库,把代码放上去,就可以在AS项目里的Gradle文件里compile ‘xxx’这样来引入你的代码了。
本文涉及到:
- 一个继承自View的自定义ProgressBar实现全过程
- 一个项目开源的全过程:使用AndroidStudio上传代码到GitHub、JCenter的过程,添加开源协议的过程等。
实现
PictureProgressBar是一个可以带图片和动画效果的进度条,可以先看看它的效果,如下图:
实现的逻辑并不复杂,看看流程图:
主要的逻辑是在onDraw()方法实现,里面大量利用到Canvas,Canvas的使用可以参考下我以前这篇笔记。
1.初始化属性
由于前面的属性定义太多了,所以这里不列出来,后面要用到的属性会有介绍,想详细了解的可以看GitHub的介绍文档,那里有个表详细介绍。这里定义初始化方法,用来配置画笔和设置Gradient渐变器,由于Gradient需要进度条的宽高,所以要在Measure过程之后才配置:
//初始化
private void init() {
//初始化画笔
paintPicture = new Paint();
paintBackGround = new Paint();
paintBackGround.setColor(backGroundColor);
paintBar = new Paint();
paintBar.setColor(barColor);
if (isGradient) {
//在PreDraw时获取View属性,因为在初始化的时候View还没进行Measure
getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
linearGradient = new LinearGradient(0, progressHeight / 2, progressWidth, progressHeight / 2, gradientStartColor, gradientEndColor, Shader.TileMode.CLAMP);
paintBar.setShader(linearGradient);
return false;
}
});
}
}
2.画进度条
首先就是要画好进度条,Android源码自带的ProgressBar是基于事件机制来刷新View的,也就是每当有进度改变才会调用刷新View的方法,但是因为我这里要实现动画而且对怎么实现事件机制不是很熟,所以采用了定时刷新的方法,先把进度条画出来:
//画进度条
private void drawBar(Canvas canvas){
if (isRound) {
//画圆角矩形
rectFBG.set(0, y - progressHeight / 2 + progressHeightOffset,
progressWidth, y + progressHeight / 2 + progressHeightOffset);
canvas.drawRoundRect(rectFBG, roundX, roundY, paintBackGround);
rectFPB.set(0, y - progressHeight / 2 + progressHeightOffset,
x, y + progressHeight / 2 + progressHeightOffset);
canvas.drawRoundRect(rectFPB, roundX, roundY, paintBar);
} else {
//画矩形
rectFBG.set(0, 0, getWidth(), getHeight());
canvas.drawRect(rectFBG, paintBackGround);
canvas.drawRect(0, 0, x, getHeight(), paintBar);
}
}
简单说一下上面的一些属性:
- isRound是决定进度条是否圆角的boolean变量,由于觉得不是圆角的进度条有点难看,所以就最终发布时默认初始设置是true。
- progressWidth和progressHeight是进度条的宽高,而不是整个View的宽高,因为View是包括进度条和图片,要为图片的显示预留空间,所以进度条宽高会在onMeasure()根据属性设置来定义大小(具体怎么定义后面说)。
- x和y是当前进度的中心点坐标位置。
- progressHeightOffset是进度条的所处高度偏移量,负数为向上偏移,正数为向下偏移。前面就说过progressHeight是进度条的宽高不一定是整个View的宽高,所以进度条可以处于一个自定义的位置(目前仅仅是高度,因为一般都不用设置宽度)。具体的效果可以看前面demo效果的第一个,进度条就是向下偏移而实现了被可爱的丘比龙踩在脚下的效果。
3.画图片Drawable
接下来是画图片Drawable的方法,这个Drawable可以是图片或者是Shape,根据当前进度的中心点坐标x、y和图片的半宽高属性halfDrawableWidth、halfDrawableHeight来实现,其中drawableHeightOffset是图片的高度偏移量:
//画图
private void drawPicture(Canvas canvas) {
if (drawable == null && animMode != ANIM_NULL){
Log.e(TAG,"drawable is null");
return;
}
drawable.setBounds(x - halfDrawableWidth,
getHeight() / 2 - halfDrawableHeight + drawableHeightOffset,
x + halfDrawableWidth,
getHeight() / 2 + halfDrawableHeight + drawableHeightOffset);
drawable.draw(canvas);
}
4.画动画:
先对是否开启动画,当前动画模式做出判断,实现5个动画模式:
<animMode模式 | 意义 |
---|---|
ANIM_NULL | 无动画模式 |
ANIM_ROTATE | 旋转动画模式 |