结合上篇的OkHttpUtils,本篇我来制作一款支持圆形和圆角矩形的ProgressBar,来装一下b。
注释:本ProgressView支持圆形和圆角矩形(代码中为HORIZONTAL何VERTICALITY两种模式)
先来看看效果吧,下载QQ.apk文件,实现进度条实时更新
是不是比原生的ProgressBar好看多了?有木有,哈哈。好了,来看看如何搞定该自定义View
1.初始化背景
private void init() {
mPaint = new Paint();
//是否填充
mPaint.setStyle(Paint.Style.FILL);
//是否平滑
mPaint.setAntiAlias(true);
//画笔的宽度
mPaint.setStrokeWidth(mProgressSize);
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
textPaint.setStyle(Paint.Style.FILL);
textPaint.setAntiAlias(true);
textPaint.setTextSize(20);
textPaint.setColor(0xff333333);
textRect = new Rect();
//得到“100%”’字符的宽度为后面画文字做准备
String str = "100%";
textPaint.getTextBounds(str,0,str.length(),textRect);
textWidth = textRect.right - textRect.left;
}
一般在onSizeChanged()方法中获得有关长度的信息
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//初始化半径
if (mRadius == 0) {
//初始化所需要的长度
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
mRadius = Math.min(mWidth, mHeight);
mPoint = new Point(mWidth / 2, mHeight / 2);
mRectF = new RectF(0, 0, mWidth, mHeight);
}
}
重写onDraw()方法即可
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE, PorterDuff.Mode.DST_OVER);
mPaint.setColor(mBackGroundColor);
mPaint.setStyle(Paint.Style.FILL);
switch (mOrientation) {
case HORIZONTAL:
//重置绘制区域
mRectF.set(0, 0, mWidth-textWidth, mHeight);
//初始化背景,(区域,x轴弧度,y轴弧度,画笔)
canvas.drawRoundRect(mRectF, mArc, mArc, mPaint);
//根据进度来绘制进度区域
drawHorizontal(canvas);
break;
case VERTICALITY:
mPaint.setStrokeWidth(mProgressSize);
mPaint.setColor(0xfff2f2f2);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(mPoint.x, mPoint.y, mRadius / 2 - mProgressSize, mPaint);
drawVerticality(canvas);
break;
}
//绘制进度文字
drawText(canvas);
}
2.绘制进度条
public void drawHorizontal(Canvas canvas) {
mPaint.setColor(mColor);
mRectF.set(0, 0, mLength, mHeight);
//绘制圆角矩形
canvas.drawRoundRect(mRectF, mArc, mArc, mPaint);
}
public void drawVerticality(Canvas canvas) {
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(mColor);
mPaint.setStrokeWidth(mProgressSize + 1);
mRectF.set(mProgressSize, mProgressSize, mRadius - mProgressSize, mRadius - mProgressSize);
//绘制圆弧(绘制区域,起始角度,终止角度,是否是封闭图形,画笔)
canvas.drawArc(mRectF, 0, mAngle, false, mPaint);
}
3.绘制进度文字信息
drawText的基准是文字相对于BaseLine的左下角,-left,-top是文字在左上角的位置,根据左上角就可以让文字在任何位置。
private void drawText(Canvas canvas) {
String str = mProgress + "%";
textPaint.getTextBounds(str, 0, str.length(), textRect);
int w = textRect.right - textRect.left;
int h = textRect.bottom - textRect.top;
switch (mOrientation) {
case HORIZONTAL:
//得到相对于baseLine的x,y
int x = (int) (-textRect.left+(mProgress/100.0)*(mWidth-textWidth));
int y = (-textRect.top+(mHeight-h)/2);
canvas.drawText(str,x,y,textPaint);
break;
case VERTICALITY:
int l = (mRadius - w) / 2;
int t = (mRadius - h) / 2;
canvas.drawText(str, -textRect.left + l, -textRect.top + t, textPaint);
break;
}
}
4.接受外界的进度信息
public synchronized void setProgress(int progress) {
if (progress < 0 || progress > 100)
throw new RuntimeException("the progress must in [0 , 100]");
mProgress = progress;
switch (mOrientation) {
case HORIZONTAL:
//根据进度算出长度
mLength = (float) ((progress / 100.0) * (mWidth-textWidth));
break;
case VERTICALITY:
//根据进度算出角度
mAngle = (float) ((progress / 100.0) * 360);
break;
}
//让View调用onDraw方法,冲绘
invalidate();
}
5.外界产生进度事件
private void download() {
final File file = FileUtils.getFile("yzzTest.mp3");
if (file == null) return;
OkUtils.getInstance().doGet(PATH, OkCallback.getInstance().callback(new BasCallBackImpl() {
@Override
public void success(Response response) {
try {
long count = 0;
int len = 0;
byte[] bytes = new byte[1024];
final Long length = response.body().contentLength();
InputStream inputStream = response.body().byteStream();
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
OutputStream outputStream = new FileOutputStream(file);
BufferedOutputStream out = new BufferedOutputStream(outputStream);
while ((len = bufferedInputStream.read(bytes)) != -1) {
count += len;
out.write(bytes, 0, len);
final long finalCount = count;
progressViewH.post(new Runnable() {
@Override
public void run() {
progressViewH.setProgress((int) (finalCount*100 /length*1.0));
}
});
progressViewV.post(new Runnable() {
@Override
public void run() {
progressViewV.setProgress((int) (finalCount*100 /length*1.0));
}
});
}
out.flush();
out.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}));
}
好了,经过这5步,就实现了自定义ProgressBar,是不是很容易,觉得好给个赞呗。github地址:https://github.com/yzzAndroid/OnLnePlayer