Android自定义圆形下载进度条,Android自定义之圆形进度条

先来看看效果图,有图才有真相:

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

Usage

Android Studio 使用Gradle构建

dependencies { compile 'com.github.ws.circleprogress:circleprogress:2.0.4' }

Maven

com.github.ws.circleprogress

circleprogress

2.0.4

pom

eclipse

完成上面的依赖后,在布局文件中声明控件:

android:id="@+id/cpb0"

android:layout_width="200dp"

android:layout_height="200dp" />

CircleProgressBar可以替换为CircleProgressArc或者CircleProgressRise,替换成哪种进度条,根据你具体情况而定。

Activity文件中:

cpb = (CircleProgressBar) findViewById(R.id.cpb1);

这样一个简单的进度条就出现在我们的眼前了:

0818b9ca8b590ca3270a3433284dd417.png

Attribute

每次间隔多少时间移动

setDelayTime(int delayTime)

是否加速移动 默认加速移动

setIsAcc(boolean mBool)

设置文字颜色

setTextColor(int color)

设置最大进度

setMinProgress(int minProgress)

设置最小进度

setMinProgress(int minProgress)

设置文字大小

setTextSize(float percent) //0.0f到1.0f

设置背景 空心圆大小

setBackgroundStoreWidth(int width)

其他的一些属性

/** * 设置背景颜色 * *@param color */

public void setBackgroundColor(int color) {

backgroundPaint.setColor(color);

}

/** * 设置背景风格 * *@param style */

public void setBackgroundStyle(Paint.Style style) {

backgroundPaint.setStyle(style);

}

/** * 设置bar空心宽度大小 * *@param width */

public void setBarStoreWidth(int width) {

barPaint.setStrokeWidth(DensityUtil.dip2px(mContext, width));

}

/** * 设置bar的颜色 * *@param color */

public void setBarColor(int color) {

barPaint.setColor(color);

}

/** * 设置bar风格 * *@param style */

public void setBarStyle(Paint.Style style) {

barPaint.setStyle(style);

}

Realization

接下来我以Bar进度条为例,讲讲实现过程。原理非常简单:间隔多少时间重绘界面画弧度。需要注意的是:不要直接new Handler(),可能会引起OOM,原因是:非静态的匿名内部类持有外部类的一个引用。推荐使用方法:

protected static class MyHandler extends Handler {

private WeakReference activityWeakReference;

public MyHandler(BaseCircleProgress circle) {

activityWeakReference = new WeakReference(circle);

}

@Override

public void handleMessage(Message msg) {

BaseCircleProgress circle = activityWeakReference.get();

if (circle == null) {

return;

}

}

}

onMeasure

主要是处理wrap_content无效的问题。我这里就直接贴代码,没什么技巧在里面:

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width;

int height;

int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.EXACTLY) {

height = heightSpecSize;

width = Math.min(heightSpecSize, Math.min(DensityUtil.getScreenSize(mContext)[0], DensityUtil.getScreenSize(mContext)[1]));

} else if (widthSpecMode == MeasureSpec.EXACTLY && heightSpecMode == MeasureSpec.AT_MOST) {

width = widthSpecSize;

height = Math.min(widthSpecSize, Math.min(DensityUtil.getScreenSize(mContext)[0], DensityUtil.getScreenSize(mContext)[1]));

} else if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {

width = height = Math.min(DensityUtil.getScreenSize(mContext)[0], DensityUtil.getScreenSize(mContext)[1]);

} else {

width = widthSpecSize;

height = heightSpecSize;

}

setMeasuredDimension(width, height);

}

由于我们不需要设定控件位置,所有不需要处理onLayout方法。

onSizeChanged

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

super.onSizeChanged(w, h, oldw, oldh);

circleCenterX = w / 2;

circleCenterY = h / 2;

circleRadius = (int) (Math.min(circleCenterX, circleCenterY) * CIRCLE_PERCENT);

}

设定了圆形X,Y轴的坐标,半径的长度。

onDraw

我们需要在onDraw方法中绘制背景,绘制进度条,绘制文字以及间隔多少时间重绘。

绘制背景:

private void drawBackground(Canvas canvas) {

canvas.drawCircle(circleCenterX, circleCenterY, circleRadius, backgroundPaint);

}

绘制进度条:

private void drawBar(Canvas canvas) {

RectF f = new RectF(circleCenterX - circleRadius, circleCenterY - circleRadius, circleCenterX + circleRadius, circleCenterY + circleRadius);

canvas.drawArc(f, 0f, ((float) currentProgress / MAX_PROGRESS) * ROUND_ANGLE, false, barPaint);

}

绘制文字:

private void drawText(Canvas canvas) {

Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();

float fontHeight = fontMetrics.descent - fontMetrics.ascent; //文字的高度

textPaint.setTextAlign(Paint.Align.CENTER);

textPaint.setTextSize(circleRadius * textPercent);

canvas.drawText(currentProgress + mUnit, circleCenterX, circleCenterY + (fontHeight / 4), textPaint);

}

注意:fontHeight / 4一直有争议,设定文字位于圆的中心,本应fontHeight / 2,可是测试的时候文字往下移动了,静止不动的时候是正确的,可是运动起来就不对了。

更新进度条:

private void updateProgress() {

if (currentProgress < maxProgress) {

currentProgress++;

if (isAcc) {

delayTime--;

}

handler.postDelayed(new Runnable() {

@Override

public void run() {

postInvalidate();

}

}, delayTime);

}

}

当然你可能有更好的建议和方案,可以给我留言。学习很多时候就是在积累经验。源码地址请关注https://github.com/HpWens/ProgressDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值