项目有需求,进度条需要显示三种比例的进度条显示,网上找的现有的自定义进度条都是显示两个数据的比例,不能满足需求,只能自己写一个自定义进度条view了。
1.自定义view控件
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class CustomHorizontalProgres extends View {
float initData1 = 40;//进度1
float initData2 = 20;//进度2
float initData3 = 40;//进度3
//默认值
private static final int DEAFUALT_PROGRESS_UNREACH_HEIGHH = 10;//dp
private static final int DEAFUALT_PROGRESS_REACH_HEIGHH = 10;//dp
private static final int DEAFUALT_PROGRESS_TEXT_SIZE = 10;//sp
private static final int DEAFUALT_PROGRESS_TEXT_CORLOR = 0xFFD3D6DA;
private static final int DEAFUALT_PROGRESS_VIEW_WIDTH = 200;//进度条默认宽度
private int HorizontalProgresUnReachHeight;
private int HorizontalProgresReachHeight;
private int HorizontalProgresTextColor;
private int HorizontalProgresTextSize;
private Paint mPaint = new Paint();
public CustomHorizontalProgres(Context context) {
this(context,null);
}
public CustomHorizontalProgres(Context context, AttributeSet attrs) {
this(context,attrs,0);
}
public CustomHorizontalProgres(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
geStyleabletAttr(attrs);
mPaint.setTextSize(HorizontalProgresTextSize);//设置画笔文字大小
mPaint.setColor(HorizontalProgresTextColor);
}
/**
* 获取自定义属性
*/
private void geStyleabletAttr(AttributeSet attrs) {
TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CustomHorizontalProgresStyle);
//将sp、dp统一转换为sp
HorizontalProgresReachHeight = (int) typedArray.getDimension
(R.styleable.CustomHorizontalProgresStyle_HorizontalProgresReachHeight,dp2px(getContext(),DEAFUALT_PROGRESS_REACH_HEIGHH));
HorizontalProgresUnReachHeight = (int) typedArray.getDimension
(R.styleable.CustomHorizontalProgresStyle_HorizontalProgresUnReachHeight,dp2px(getContext
(),DEAFUALT_PROGRESS_UNREACH_HEIGHH));
HorizontalProgresTextColor = typedArray.getColor
(R.styleable.CustomHorizontalProgresStyle_HorizontalProgresTextColor,DEAFUALT_PROGRESS_TEXT_CORLOR);
HorizontalProgresTextSize = (int) typedArray.getDimension
(R.styleable.CustomHorizontalProgresStyle_HorizontalProgresTextSize,sp2px(getContext(),DEAFUALT_PROGRESS_TEXT_SIZE));
typedArray.recycle();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = measureWidth(widthMeasureSpec);//计算宽高
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width,height);//设置宽高
}
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();//save、restore 图层的保存和回滚相关的方法
canvas.translate(0,getHeight()/2);//移动图层到垂直居中位置
float realWidth = getWidth() - getPaddingLeft() - getPaddingRight()-35-15;//实际控件宽度
//1
int initX1 = 15;//初始x坐标
int initY1 = 0;//初始y坐标
int rightupLength1 = (int) (initData1/100*realWidth);//占比宽
int rightdownLength1 = rightupLength1+25;//rightupLength1+25,40
int leftdownLength1 = 25;//25,40
mPaint.setColor(Color.rgb(220, 20, 60));//红色
//绘制路径
Path path = new Path();
if(initData2 == 0 && initData3!=0){
//从哪个点开始绘制
path.moveTo(initX1 ,initY1);//1
//然后绘制到哪个点
path.lineTo(initX1+rightupLength1-10,initY1);//2 进度1长度右上x,y
//然后再绘制到哪个点
path.lineTo(initX1+rightdownLength1-10,initY1+40);//3 进度1长度右下x,y y为高度 -13为了添加进度间隙
//然后再绘制到哪个点
path.lineTo(leftdownLength1,initY1+40);//4 进度1长度左下x,y
//然后再绘制到哪个点
path.lineTo(initX1,initY1);//5 进度1长度左上x,y
}else{
//从哪个点开始绘制
path.moveTo(initX1 ,initY1);//1
//然后绘制到哪个点
path.lineTo(initX1+rightupLength1,initY1);//2 进度1长度右上x,y
//然后再绘制到哪个点
path.lineTo(initX1+rightdownLength1-13,initY1+40);//3 进度1长度右下x,y y为高度 -13为了添加进度间隙
//然后再绘制到哪个点
path.lineTo(leftdownLength1,initY1+40);//4 进度1长度左下x,y
//然后再绘制到哪个点
path.lineTo(initX1,initY1);//5 进度1长度左上x,y
}
if(rightupLength1!=0) {
//按路径绘制,就是一个菱形
canvas.drawPath(path, mPaint);
}else{
mPaint.setColor(Color.rgb(85, 123, 205));//绿色
}
RectF oval1 = new RectF(initX1-15, initY1, 60, 40);// 设置个新的长方形
canvas.drawRoundRect(oval1,20,20,mPaint);//圆角矩形
//2
int initX2 = initX1+rightupLength1;//初始x坐标
int initY2 = 0;//初始y坐标
int rightupLength2 = (int) (initData2/100*realWidth);//占比宽
int rightdownLength2 = rightdownLength1+rightupLength2;
int leftdownLength2 = leftdownLength1+rightupLength1;
mPaint.setColor(Color.GRAY);
//绘制路径
Path path2 = new Path();
//从哪个点开始绘制
path2.moveTo( initX2+10,initY2);//1 +10为了进度间隙
//然后绘制到哪个点
path2.lineTo(initX2+rightupLength2-10,initY2);//2 -10为了进度间隙
//然后再绘制到哪个点
path2.lineTo(rightdownLength2-10,initY2+40);//3 -10为了进度间隙
//然后再绘制到哪个点
path2.lineTo(leftdownLength2+10,initY2+40);//4 +10为了进度间隙
//然后再绘制到哪个点
path2.lineTo(initX2+10,initY2);//5 +10为了进度间隙
if(rightupLength2!=0) {
//按路径绘制,就是一个菱形
canvas.drawPath(path2, mPaint);
}
//3
int initX3 = initX1+rightupLength1+rightupLength2;//初始x坐标
int initY3 = 0;//初始y坐标
int rightupLength3 = (int) (initData3/100*realWidth);//占比宽
int rightdownLength3 = rightdownLength2+rightupLength3;
int leftdownLength3 = leftdownLength2+rightupLength2;
if(rightupLength3 != 0){
mPaint.setColor(Color.rgb(85, 123, 205));//绿色
}else{
mPaint.setColor(Color.rgb(220, 20, 60));//红色
}
//绘制路径
Path path3 = new Path();
if(rightupLength2 == 0 || rightupLength3 ==0){
//从哪个点开始绘制
path3.moveTo(initX3 ,initY3);//1 +10为了添加进度
//然后绘制到哪个点
path3.lineTo(initX3+rightupLength3-10,initY3);//2 -10为了添加进度
//然后再绘制到哪个点
path3.lineTo(rightdownLength3-10,initY3+40);//3 -10为了添加进度
//然后再绘制到哪个点
path3.lineTo(leftdownLength3+15,initY3+40);//4 +10为了添加进度
//然后再绘制到哪个点
path3.lineTo(initX3,initY3);//5 +10为了添加进度
RectF oval3 = new RectF(rightdownLength3-25-10, initY3, rightdownLength3-25-10+40, 40);// 设置个新的长方形
canvas.drawRoundRect(oval3,20,20,mPaint);//圆角矩形
}else{
//从哪个点开始绘制
path3.moveTo(initX3 ,initY3);//1
//然后绘制到哪个点
path3.lineTo(initX3+rightupLength3,initY3);//2
//然后再绘制到哪个点
path3.lineTo(rightdownLength3,initY3+40);//3
//然后再绘制到哪个点
path3.lineTo(leftdownLength3,initY3+40);//4
//然后再绘制到哪个点
path3.lineTo(initX3,initY3);//5
RectF oval3 = new RectF(rightdownLength3-25, initY3, rightdownLength3-25+40, 40);// 设置个新的长方形
canvas.drawRoundRect(oval3,20,20,mPaint);//圆角矩形
}
if(rightupLength3!=0) {
//按路径绘制,就是一个菱形
canvas.drawPath(path3, mPaint);
}
canvas.restore();
}
/**
* dp转px
*
* @param context
* @param dpVal
* @return
/
public static int dp2px(Context context, float dpVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
/*
* sp转px
*
* @param context
* @param spVal
* @return
/
public static int sp2px(Context context, float spVal)
{
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
/*
* Determines the width of this view
* @param measureSpec A measureSpec packed into an int
* @return The width of the view, honoring constraints from measureSpec
/
private int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text
result = dp2px(getContext(),DEAFUALT_PROGRESS_VIEW_WIDTH);//
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
/*
* Determines the height of this view
* @param measureSpec A measureSpec packed into an int
* @return The height of the view, honoring constraints from measureSpec
*/
private int measureHeight(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
// We were told how big to be
result = specSize;
} else {
// Measure the text (beware: ascent is a negative number)
//此处高度为走完的进度高度和未走完的机大以及文字的高度的最大值
int textHeight = (int) (mPaint.descent() - mPaint.ascent());//得到字的高度有二种方式,第一种是React,第二种这个
result = Math.max(textHeight,Math.max(HorizontalProgresReachHeight,HorizontalProgresUnReachHeight)) +
getPaddingTop()
+ getPaddingBottom();
if (specMode == MeasureSpec.AT_MOST) {
// Respect AT_MOST value if that was what is called for by measureSpec
result = Math.min(result, specSize);
}
}
return result;
}
public void setProgressData(float serviceData1,float serviceData2,float serviceData3){
this.initData1 = serviceData1;
this.initData2 = serviceData2;
this.initData3 = serviceData3;
}
}
2.调用
horizontalProgress1.setProgressData(20,30,50);
horizontalProgress2.setProgressData(60,30,10);
horizontalProgress3.setProgressData(50,0,50);
horizontalProgress4.setProgressData(0,0,100);
3.效果图
demo链接:https://download.csdn.net/download/lxy_tap/12684931