自定义View之线性百分比进度条
程序员文章站
2024-02-05 20:43:46
...
先上效果图再分析:
从图中可以看到本view支持两种不同的类型进度展示,一种是进度百分比直接用textview展示,另一种加了矩形背景。第一种没什么难度,本文就以第二种为例讲解一下,一步一步实现,你会发现原来很简单。
// 线的X起始左标
// private float startX;
// private float endX;
//private float pading = 100f; // 左右边距
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
startX = paintWidth+pading;
endX = width -pading;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 根据 progress进度 ,获得X坐标
lenth = (endX*progress/100)+startX-(progress/100*(startX));
// 底部背景线
canvas.drawLine(startX,height/2,endX,height/2,paint);
// 画 进度线
drawLine(canvas);
if (type==1){
// 不带矩形的进度
drawText(canvas);
}else if (type==2){
// 画带三角形的矩形进度条
drawRecText(canvas);
}
}
首先在onSizeChanged方法中测量view宽高和线的起始位置,在onDraw方法中进行类型判断和根据 progress进度 获得X坐标,然后开始画图。
第一步画背景线
// 底部背景线
canvas.drawLine(startX,height/2,endX,height/2,paint);
效果如下:
第二步 画进度线并实现动画效果
先画线
canvas.drawLine(startX,height/2,lenth,height/2,mPaint);
动画效果
// 设置进度
public void setProgress(int mprogress) {
ValueAnimator anim = ValueAnimator.ofFloat(0, mprogress);
anim.setDuration(3000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
progress = (float) animation.getAnimatedValue();
invalidate();
}
});
anim.start();
}
根据ValueAnimator 获取progress值,连续调用invalidate()进行重绘。
第三步实现画矩形和内部文字
String text =(int) progress+"%";
ttPaint.getTextBounds(text, 0, text.length(), tTextRect);
float TextHeight = tTextRect.height();
float TextWidth = tTextRect.width();
tRect.set((int)(lenth-TextWidth/2-4f),(int)(height/2-2*TextHeight-6f),(int)(lenth+TextWidth/2+4f),(int)(height/2-TextHeight));
// 画矩形
canvas.drawRect(tRect,recPaint);
Paint.FontMetricsInt fontMetrics = ttPaint.getFontMetricsInt();
// 获取baseLine
int baseline = tRect.top + (tRect.bottom - tRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
ttPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text,tRect.centerX(),baseline, ttPaint);
首先获取文本内容宽高,然后根据文本的宽高设置矩形的初始位置,并画出,为了不让文字紧贴矩形这里适当调整一下矩形宽高,然后在矩形的中心画出文本内容 。
第四步 画三角形
// 画三角形
path.moveTo(lenth, (float) (height/2-0.7*TextHeight));
path.lineTo((float) (lenth-0.15*TextWidth), height / 2-TextHeight);
path.lineTo((float) (lenth+0.15*TextWidth), height / 2-TextHeight);
canvas.drawPath(path, recPaint);
path.reset();
注意: 如果你问我上边方法的百分比为什么是0.15和0.7的话我会明确的告诉你我不知道!!!三角型的大小需要根据矩形的大小和位置来调整,只到你认为合适为止,所以你可以随意更改三角形的起始y坐标,连接的X坐标也可以随便更改,所以这里的百分比只是我自己调试看着顺眼。。。
全部代码
/**
* Created by Administrator on 2017/8/24 0024.
*/
public class MyLinearProgressView extends View{
private Context mcontext ;
private Paint paint ; // 初始画线笔
private Paint mPaint; // 进度画线笔
private Paint recPaint;// 矩形画笔
private float paintWidth ; // 画笔宽度
private int paintColor; // 画笔颜色
private float textSize ; // 百分比text的大小
private Paint tPaint; // 不带矩形的Text画笔
private Paint ttPaint; // 带矩形的Text画笔
// 当前进度
private float progress = 1;
/*
* view的高度
*/
private int height;
private int width;
/* 测量文本宽高的矩形 */
private Rect tTextRect;
/* 文本的矩形 */
private Rect tRect;
private float pading = 100f; // 左右边距
// 线的X起始左标
private float startX;
private float endX;
private int type ; // 那种风格
/**
* 画三角形的path
*/
private Path path = new Path();
private float lenth;
public MyLinearProgressView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mcontext = context;
getAtt(attrs);
initPaint();
}
private void getAtt(AttributeSet attrs) {
TypedArray typedArray = mcontext.obtainStyledAttributes(attrs, R.styleable.MyLinearProgressView);
paintColor = typedArray.getColor(R.styleable.MyLinearProgressView_lp_paintColor, Color.parseColor("#df0781"));
paintWidth = typedArray.getDimension(R.styleable.MyLinearProgressView_lp_paintWidth,dp2px(10));
textSize = typedArray.getDimension(R.styleable.MyLinearProgressView_lp_textSize,30f);
type = typedArray.getInt(R.styleable.MyLinearProgressView_lp_type,1);
typedArray.recycle();
tTextRect = new Rect();
tRect = new Rect();
}
private void initPaint() {
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor( Color.parseColor("#e1e1e1"));
paint.setStrokeWidth(paintWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setAntiAlias(true);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(paintWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setAntiAlias(true);
tPaint = new Paint();
tPaint.setStyle(Paint.Style.FILL);
tPaint.setColor(Color.RED);
tPaint.setStrokeWidth(paintWidth);
tPaint.setTextSize(textSize);
tPaint.setAntiAlias(true);
ttPaint = new Paint();
ttPaint.setStyle(Paint.Style.FILL);
ttPaint.setColor(Color.WHITE);
ttPaint.setStrokeWidth(paintWidth);
ttPaint.setTextSize(textSize);
ttPaint.setAntiAlias(true);
recPaint = new Paint();
recPaint.setStyle(Paint.Style.FILL);
recPaint.setColor(Color.RED);
recPaint.setAntiAlias(true);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
startX = paintWidth+pading;
endX = width -pading;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 根据 progress进度 ,获得X坐标
lenth = (endX*progress/100)+startX-(progress/100*(startX));
// 底部背景线
canvas.drawLine(startX,height/2,endX,height/2,paint);
// 画 进度线
drawLine(canvas);
if (type==1){
// 不带矩形的进度
drawText(canvas);
}else if (type==2){
// 画带三角形的矩形进度条
drawRecText(canvas);
}
}
private void drawRecText(Canvas canvas) {
String text =(int) progress+"%";
ttPaint.getTextBounds(text, 0, text.length(), tTextRect);
float TextHeight = tTextRect.height();
float TextWidth = tTextRect.width();
tRect.set((int)(lenth-TextWidth/2-4f),(int)(height/2-2*TextHeight-6f),(int)(lenth+TextWidth/2+4f),(int)(height/2-TextHeight));
// 画矩形
canvas.drawRect(tRect,recPaint);
Paint.FontMetricsInt fontMetrics = ttPaint.getFontMetricsInt();
// 获取baseLine
int baseline = tRect.top + (tRect.bottom - tRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
ttPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text,tRect.centerX(),baseline, ttPaint);
// 画三角形
path.moveTo(lenth, (float) (height/2-0.7*TextHeight));
path.lineTo((float) (lenth-0.15*TextWidth), height / 2-TextHeight);
path.lineTo((float) (lenth+0.15*TextWidth), height / 2-TextHeight);
canvas.drawPath(path, recPaint);
path.reset();
}
private void drawText(Canvas canvas) {
String text =(int) progress+"%";
tPaint.getTextBounds(text, 0, text.length(), tTextRect);
float TextHeight = tTextRect.height();
canvas.drawText(text,lenth+6f,height/2+TextHeight/2, tPaint);
}
private void drawLine(Canvas canvas) {
canvas.drawLine(startX,height/2,lenth,height/2,mPaint);
}
// 设置进度
public void setProgress(int mprogress) {
ValueAnimator anim = ValueAnimator.ofFloat(0, mprogress);
anim.setDuration(3000);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
progress = (float) animation.getAnimatedValue();
invalidate();
}
});
anim.start();
}
// 设置类型
public void setType(int mtype){
type = mtype;
invalidate();
}
/**
* dp 2 px
*
* @param dpVal
*/
protected int dp2px(int dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, getResources().getDisplayMetrics());
}
}
attr 文件
<declare-styleable name="MyLinearProgressView">
<attr name="lp_paintWidth" format="dimension"></attr>
<attr name="lp_paintColor" format="color"></attr>
<attr name="lp_textSize" format="dimension"></attr>
<attr name="lp_type" format="integer"></attr>
</declare-styleable>
地址:
csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview
上一篇: Android 自定义带入场动画的弧形百分比进度条
下一篇: 访问进度指示器