IndicateProgressBar 带指示器的ProgressBar进度条
程序员文章站
2024-02-05 20:39:34
...
github地址: https://github.com/w296365959/IndicateProgressBar
同事给的效果图索要个这样的进度条,趁着空闲时间,就做了这个
IndicateProgressBar ,这是一个简单的自定义View,带指示器的进度条。
如有 不足之处,尽情指出
转载请标明出处:
http://blog.csdn.net/w296365959/article/details/78496985
效果图:
整体思路:
先把底部背景条给画出,就是一个带圆角的矩形;
接着我们画进度条,我们可以看到进度条也是一个带圆角的矩形,同理,我们一样只要画出一个带圆角的矩形就可以了,只不过这个矩形长度是可以变化的而已,矩形左边x坐标为0,右边x坐标是背景条长度*进度比例, 我们进度条颜色是随着进度改变而渐变的,这也简单,可以直接使用Shader 来设置渐变色。这样进度画好了;
接着,画进度条的指示器,指示器室友3部分组成的,一个外框+内部填充+一个进度文本,
这都是一样 ,画个矩形就可以了,只不过给画笔颜色不同,最后在画一个文本,这文本写在矩形框内,具体数据可以自己调试。
关键代码分析:
//在ondraw里面画出进度条背景,进度,以及指示器
width = getWidth() - (int) (indicateTextPaint.measureText(max + "%") + defaultMargin);//进度条最大宽度,减去文本长度+defaultMargin 是为了放置指示器位置,
height = getHeight();
//画背景
RectF backRectF = new RectF(0, height * 2 / 5, width, height * 3 / 5);
canvas.drawRoundRect(backRectF, radius, radius, backPaint);
//画进度
RectF progressRectF = new RectF(0, height * 2 / 5, width * getScale(), height * 3 / 5);
Shader shader = new LinearGradient(0, 0, 400, 400, startProgressColor, Color.RED, Shader.TileMode.REPEAT);//渐变
progressPaint.setShader(shader);
canvas.drawRoundRect(progressRectF, radius, radius, progressPaint);
//画指示器边框
float left = getScale() * width;
float right = getScale() * width + indicateTextPaint.measureText(max + "%") + defaultMargin;
if (left <= 0f) {//当指示器最左边不在控件范围时,强制左边界=0
left = 0f;
right = indicateTextPaint.measureText(max + "%") + defaultMargin;
}
if (left >= width) {//当指示器左边界超出控件范围时,强制左边界=进度最大长度
left = width;
right = width + indicateTextPaint.measureText(max + "%") + defaultMargin;
}
RectF indicatorRectF = new RectF(left, height / 5, right, height * 4 / 5);
indicateBackPaint.setColor(textColor);
canvas.drawRoundRect(indicatorRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
//画指示器内部为白色
RectF indicatorContentRectF = new RectF(left + 2, height / 5 + 2, right - 2, height * 4 / 5 - 2);
indicateBackPaint.setColor(Color.WHITE);
canvas.drawRoundRect(indicatorContentRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
//画指示器文本
float textX = indicatorContentRectF.centerX() - indicateTextPaint.measureText(progressText) / 2;
float textY = backRectF.centerY() + height / 9;
canvas.drawText(progressText, textX, textY, indicateTextPaint);
然后,在onTouchEvent里控制 手指拖动进度条,isCanTouch可以控制是否可以拖动
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isCanTouch) {//开启可手动拖动
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();//基于控件的坐标
/*float rawX = event.getRawX();//基于屏幕的坐标
Log.i(TAG, "x==: " + x);
Log.i(TAG, "rawX==: " + rawX);
Log.i(TAG, "width==: " + width);
Log.i(TAG, "height==: " + height);*/
int count = (int) x * 100 / width;
if (count > 100) {
count = 100;
} else if (count < 0) {
count = 0;
}
progressText = count + "%";
setProgress(count);
Log.i(TAG, "progressText==: " + progressText);
invalidate();//主线程中调用刷新
// postInvalidate();//可在非UI线程中调用刷新,底层还是使用handler发送到主线程刷新重绘
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}else {
return super.onTouchEvent(event);
}
}
代码简单易懂,完整代码如下:
/**
* Author: wangzhongming<br/>
* Date : 2017/11/8 11:33 </br>
* Summary: 带指示器的进度条
*/
public class IndicateProgressBar extends View {
private float x = 10;
private String progressText = "0%";
private static final String TAG = IndicateProgressBar.class.getSimpleName();
private int width;
private int height;
private Paint backPaint;
private Paint progressPaint;
private Paint indicateTextPaint;
private Paint indicateBackPaint;
private int radius = 10; //进度条四个角的角度px
private int indicatorRadius = 32; //进度指示器四个角的角度px
private int defaultMargin = 30; //进度指示器默认多一点长度
private int max = 100;//进度最大值
private int progress = 0;//进度0-100
private boolean isCanTouch = true;//进度条是否可以手动拖动
private int startProgressColor = 0xfff29310;
private int textColor = 0xffef4f37;
private int gray = 0xfff5f5f5;
public IndicateProgressBar(Context context) {
this(context, null);
}
public IndicateProgressBar(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
// Android在用画笔的时候有三种Style,分别是
// Paint.Style.STROKE 只绘制图形轮廓(描边)//空心效果
// Paint.Style.FILL 只绘制图形内容
// Paint.Style.FILL_AND_STROKE 既绘制轮廓也绘制内容
//Paint.ANTI_ALIAS_FLAG 抗锯齿
//进度条背景画笔
backPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
backPaint.setColor(gray);
backPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//进度条进度画笔
progressPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
progressPaint.setStyle(Paint.Style.FILL);
//进度条指示器框画笔
indicateBackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
indicateBackPaint.setColor(textColor);
indicateBackPaint.setTextSize(32);
//进度条指示器文本画笔
indicateTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
indicateTextPaint.setColor(textColor);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
width = getWidth() - (int) (indicateTextPaint.measureText(max + "%") + defaultMargin);
height = getHeight();
//画背景
RectF backRectF = new RectF(0, height * 2 / 5, width, height * 3 / 5);
canvas.drawRoundRect(backRectF, radius, radius, backPaint);
//画进度
RectF progressRectF = new RectF(0, height * 2 / 5, width * getScale(), height * 3 / 5);
Shader shader = new LinearGradient(0, 0, 400, 400, startProgressColor, Color.RED, Shader.TileMode.REPEAT);//渐变
progressPaint.setShader(shader);
canvas.drawRoundRect(progressRectF, radius, radius, progressPaint);
//画指示器边框
float left = getScale() * width;
float right = getScale() * width + indicateTextPaint.measureText(max + "%") + defaultMargin;
if (left <= 0f) {
left = 0f;
right = indicateTextPaint.measureText(max + "%") + defaultMargin;
}
if (left >= width) {
left = width;
right = width + indicateTextPaint.measureText(max + "%") + defaultMargin;
}
RectF indicatorRectF = new RectF(left, height / 5, right, height * 4 / 5);
indicateBackPaint.setColor(textColor);
canvas.drawRoundRect(indicatorRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
//画指示器内部为白色
RectF indicatorContentRectF = new RectF(left + 2, height / 5 + 2, right - 2, height * 4 / 5 - 2);
indicateBackPaint.setColor(Color.WHITE);
canvas.drawRoundRect(indicatorContentRectF, indicatorRadius, indicatorRadius, indicateBackPaint);
//画指示器文本
float textX = indicatorContentRectF.centerX() - indicateTextPaint.measureText(progressText) / 2;
float textY = backRectF.centerY() + height / 9;
canvas.drawText(progressText, textX, textY, indicateTextPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (isCanTouch) {//开启可手动拖动
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
x = event.getX();//基于控件的坐标
/*float rawX = event.getRawX();//基于屏幕的坐标
Log.i(TAG, "x==: " + x);
Log.i(TAG, "rawX==: " + rawX);
Log.i(TAG, "width==: " + width);
Log.i(TAG, "height==: " + height);*/
int count = (int) x * 100 / width;
if (count > 100) {
count = 100;
} else if (count < 0) {
count = 0;
}
progressText = count + "%";
setProgress(count);
Log.i(TAG, "progressText==: " + progressText);
invalidate();//主线程中调用刷新
// postInvalidate();//可在非UI线程中调用刷新,底层还是使用handler发送到主线程刷新重绘
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}else {
return super.onTouchEvent(event);
}
}
/**
* 是否开启拖动有效
* 默认可以手动拖动
*
* @param isOpen true开启可以手动拖动
*/
public void setCanTouch(boolean isOpen) {
isCanTouch = isOpen;
}
/**
* 设置进度,getScale()内会调用
*
* @param progress 0-100 ,最大进度默认100
*/
public void setProgress(int progress) {
this.progress = progress;
}
/**
* 设置进度,getScale()内会调用
*
* @param progress 进度 0-100
* @param max 最大进度 ,不写则默认100
*/
public void setProgress(int progress, int max) {
this.progress = progress;
this.max = max;
}
/**
* 进度显示百分数
*
* @param strText 如写 70%
*/
private void setProgeressText(String strText) {
progressText = strText;
}
/**
* 进度比例小数
*
* @return
*/
private float getScale() {
float scale;
if (max == 0) {
scale = 0;
} else {
scale = (float) progress / (float) max;
}
setProgeressText((int) (scale * 100) + "%");
return scale;
}
}
好了,一个简单的带指示器的进度条完成了!
推荐阅读
-
IndicateProgressBar 带指示器的ProgressBar进度条
-
Android中的常用控件之进度条(ProgressBar)
-
我的Android进阶之旅------>Android之进度条(ProgressBar)的功能和用法
-
Android中ProgressBar的使用-通过Handler与Message实现进度条显示
-
Java swing 带界面和进度条的多线程下载器实现
-
ajax做出带百分比的进度条(附代码)
-
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO_PHP教程
-
Android带播放进度条的音乐播放器
-
Android ProgressBar进度条和ProgressDialog进度框的展示DEMO
-
Android实现带数字的圆形进度条(自定义进度条)