先上效果图:

loading.gif

以下代码直接复制即可使用, 碰到类似样式的, 可以根据自己需求修改.

①. 在arrts.xml添加对应属性.

②. 把源码复制过去即可使用.

1. 圆弧进度条 ArcProgressView

ArcProgressView.png

属性:

//中间文字

//文字大小

//文字颜色

//进度条 内层颜色

//进度条 外层颜色

//进度条 内层大小

//进度条 外层大小

//开始角度

//绘制角度,默认360, 例如:180时为一个半圆

使用: 其它View使用方式一样

android:id="@+id/arc_view"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginLeft="200dp"

app:liys_progress_arc_inCircleColor="#EDEDED"

app:liys_progress_arc_textSize="15dp"

app:liys_progress_arc_text="0%"/>

2. 线性进度条 LineTextProgressView

LineTextProgressView.png

属性:

//文字

//文字大小

//文字颜色

//进度条 内层大小

//进度条 外层大小

//进度条 内层颜色

//进度条 外层颜色

3. 水平进度条(带文字) HorzTextProgressView

HorzTextProgressView.png

属性

//文字

//文字大小

//文字颜色

//进度条 内层大小

//进度条 外层大小

//进度条 内层颜色

//进度条 外层颜色

4. 水平进度条(不带文字) HorzProgressView

HorzProgressView.png

属性:

//最大值

//当前进度值

//进度条 外层大小

//进度条 内层颜色

//进度条 外层颜色

//进度条 内层图片(可选)

//进度条 外层图片(可选)

5. 水波 进度条 WaterWaveProView

WaterWaveProView.png

属性:

//中间文字内容

//文字大小

//文字颜色

//内层颜色

//外层颜色

>>>>>>>>>>>>>>>>>>>>>>>>附上源码>>>>>>>>>>>>>>>>>>>>>>>>>>>>

/**

* 圆弧进度条

* @author liys 401654546@qq.com

* @version 1.0 2018/09/12

*/

public class ArcProgressView extends View {

private double mMaxNum = 10000; //最大值

private double mCurrentNum = 0; //当前的值

private String mText = "0%"; //当前 百分比

private int mTextSize; //字体大小

private int mTextColor = 0; //字体颜色

private int mInColor = 0; //内圈颜色

private int mOutColor = 0; //外圈颜色

private int mInCircleSize; //外圈大小 单位sp

private int mOutCircleSize; //内圈大小 单位sp

private int mStartAngle; //开始角度

private int mDrawAngle; //需要绘制的角度

private int mCurrentAngle = 0; //当前角度

private int mWidth; //宽

private int mHeight; //高

int defaultWidth = 100; //默认宽高,单位sp

//画笔

private Paint mTextPaint;

private Paint mInPaint;

private Paint mOutPaint;

public ArcProgressView(Context context) {

this(context, null, 0);

}

public ArcProgressView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public ArcProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

//默认值

int defaultTextSize = 20; //默认字体大小

int defaultCircleSize = 10; //默认圆弧大小 单位sp

int defaultStartAngle = -90; //默认开始角度

int defaultDrawAngle = 360; //默认绘制角度

String defaultTextColor = "#ABC4DF"; //默认字体颜色

String defaultInColor = "#EDEDED"; //默认内颜色

String defaultOutColor = "#CCBD00"; //默认外颜色

// 获取自定义属性

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArcProgressView);

mText = typedArray.getString(R.styleable.ArcProgressView_liys_progress_arc_text);

mTextSize = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_liys_progress_arc_textSize, sp2px(defaultTextSize));

mStartAngle = typedArray.getInt(R.styleable.ArcProgressView_liys_progress_arc_startAngle, defaultStartAngle);

mDrawAngle = typedArray.getInt(R.styleable.ArcProgressView_liys_progress_arc_drawAngle, defaultDrawAngle);

mTextColor = typedArray.getColor(R.styleable.ArcProgressView_liys_progress_arc_textColor, Color.parseColor(defaultTextColor));

mInColor = typedArray.getColor(R.styleable.ArcProgressView_liys_progress_arc_inCircleColor, Color.parseColor(defaultInColor));

mOutColor = typedArray.getColor(R.styleable.ArcProgressView_liys_progress_arc_outCircleColor, Color.parseColor(defaultOutColor));

mInCircleSize = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_liys_progress_arc_inCircleSize, sp2px(defaultCircleSize));

mOutCircleSize = typedArray.getDimensionPixelSize(R.styleable.ArcProgressView_liys_progress_arc_outCircleSize, sp2px(defaultCircleSize));

typedArray.recycle();

//设置画笔

mTextPaint = new Paint();

mInPaint = new Paint();

mOutPaint = new Paint();

setTextPaint();

setInPaint();

setOutPaint();

}

/**

* 文字画笔

*/

private void setTextPaint() {

mTextPaint.setColor(mTextColor);

mTextPaint.setAntiAlias(true);

mTextPaint.setTextSize(mTextSize);

}

/**

* 内圆弧画笔

*/

private void setInPaint() {

mInPaint.setColor(mInColor);

mInPaint.setAntiAlias(true);

mInPaint.setStrokeWidth(mInCircleSize); //大小

mInPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

mInPaint.setStyle(Paint.Style.STROKE); //空心样式

}

/**

* 外圆弧画笔

*/

private void setOutPaint() {

mOutPaint.setColor(mOutColor);

mOutPaint.setAntiAlias(true);

mOutPaint.setStrokeWidth(mOutCircleSize); //大小

mOutPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

mOutPaint.setStyle(Paint.Style.STROKE); //空心样式

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//取默认值

mWidth = sp2px(defaultWidth);

mHeight = sp2px(defaultWidth);

//1. 获取宽

if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mWidth = MeasureSpec.getSize(widthMeasureSpec);

}

//2.获取高

if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mHeight = MeasureSpec.getSize(heightMeasureSpec);

}

//3. 确定宽高(保持宽高一致)

mWidth = mHeight = (mWidth > mHeight ? mHeight : mWidth);

setMeasuredDimension(mWidth, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawText(canvas);

drawInCircle(canvas);

drawOutCircle(canvas);

}

//内圆弧

private void drawInCircle(Canvas canvas) {

int r = mInCircleSize / 2; //圆弧的一半

RectF rectF = new RectF(r, r, mWidth - r, mHeight - r);

canvas.drawArc(rectF, mStartAngle, mDrawAngle, false, mInPaint);

}

//内圆弧

private void drawOutCircle(Canvas canvas) {

int r = mOutCircleSize / 2; //圆弧的一半

RectF rectF = new RectF(r, r, mWidth - r, mHeight - r);

if (mCurrentAngle > mDrawAngle) {

mCurrentAngle = mDrawAngle;

}

canvas.drawArc(rectF, mStartAngle, mCurrentAngle, false, mOutPaint);

}

private void drawText(Canvas canvas) {

//1. 获取绘制字体区域

Rect bounds = new Rect();

mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);

//2.获取准线

Paint.FontMetricsInt metrics = mTextPaint.getFontMetricsInt();

int dy = (metrics.bottom - metrics.top) / 2 - metrics.bottom;

int baseLine = mHeight / 2 + dy;

//3.绘制文字

canvas.drawText(mText, mWidth / 2 - bounds.width() / 2, baseLine, mTextPaint);

}

private int sp2px(int sp) {

return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,

getResources().getDisplayMetrics());

}

public void setMaxNum(double maxNum) {

this.mMaxNum = maxNum;

}

public void setCurrentNum(double currentNum) {

this.mCurrentNum = currentNum;

//计算角度 mCurrentStep/mMaxStep = mCurrentAngle/mDrawAngle;

mCurrentAngle = (int)(currentNum * mDrawAngle / mMaxNum);

mText = new DecimalFormat("0.00%").format(mCurrentNum/mMaxNum);

invalidate();

}

}

/**

* 线性进度条

* @author liys 401654546@qq.com

* @version 1.0 2018/09/12

*/

public class LineTextProgressView extends View{

private double mMaxNum = 10000; //最大值

private double mCurrentNum = 0; //当前的值

private String mText = "0%"; //当前 百分比

private int mTextSize; //字体大小

private int mTextColor = 0; //字体颜色

private int mInLineColor = 0; //内线颜色

private int mOutLineColor = 0; //外线颜色

private int mInLineSize; //外线 大小 单位sp

private int mOutLineSize; //内线 大小 单位sp

private int mWidth; //宽

private int mHeight; //高

int mDefaultWidth = 300; //默认宽,单位sp

int mDefaultHeight = 30; //默认高,单位sp

int mTriangleValue = 8;

//画笔

private Paint mTextPaint;

private Paint mInPaint;

private Paint mOutPaint;

private Paint mBoxPaint;

public LineTextProgressView(Context context) {

this(context, null);

}

public LineTextProgressView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs,0);

}

public LineTextProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

//默认值

int defaultTextSize = 10; //默认字体大小 单位sp

String defaultTextColor = "#FFFFFF"; //默认字体颜色

String defaultInColor = "#EDEDED"; //默认内颜色

String defaultOutColor = "#CCBD00"; //默认外颜色

int defaultLineSize = 10; //默认线的大小 单位sp

// 获取自定义属性

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.LineTextProgressView);

mText = typedArray.getString(R.styleable.LineTextProgressView_liys_progress_line_text);

mTextColor = typedArray.getColor(R.styleable.LineTextProgressView_liys_progress_line_textColor, Color.parseColor(defaultTextColor));

mInLineColor = typedArray.getColor(R.styleable.LineTextProgressView_liys_progress_line_inLineColor, Color.parseColor(defaultInColor));

mOutLineColor = typedArray.getColor(R.styleable.LineTextProgressView_liys_progress_line_outLineColor, Color.parseColor(defaultOutColor));

mTextSize = typedArray.getDimensionPixelSize(R.styleable.LineTextProgressView_liys_progress_line_textSize, sp2px(defaultTextSize));

mInLineSize = typedArray.getDimensionPixelSize(R.styleable.LineTextProgressView_liys_progress_line_inLineSize, sp2px(defaultLineSize));

mOutLineSize = typedArray.getDimensionPixelSize(R.styleable.LineTextProgressView_liys_progress_line_outLineSize, sp2px(defaultLineSize));

typedArray.recycle();

setTextPaint();

setInPaint();

setOutPaint();

setBoxPaint();

if(mText == null){

mText = "00.00%";

}

}

/**

* 方框画笔

*/

private void setBoxPaint() {

mBoxPaint = new Paint();

mBoxPaint.setAntiAlias(true);

mBoxPaint.setColor(mOutLineColor);

}

/**

* 文字画笔

*/

private void setTextPaint() {

mTextPaint = new Paint();

mTextPaint.setAntiAlias(true);

mTextPaint.setColor(mTextColor);

mTextPaint.setTextSize(mTextSize);

}

/**

* 内线画笔

*/

private void setInPaint() {

mInPaint = new Paint();

mInPaint.setAntiAlias(true);

mInPaint.setColor(mInLineColor);

mInPaint.setStrokeWidth(mInLineSize); //大小

mInPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

/**

* 外线画笔

*/

private void setOutPaint() {

mOutPaint = new Paint();

mOutPaint.setAntiAlias(true);

mOutPaint.setColor(mOutLineColor);

mOutPaint.setStrokeWidth(mOutLineSize); //大小

mOutPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//取默认值

mWidth = sp2px(mDefaultWidth);

mHeight = sp2px(mDefaultHeight);

//1. 获取宽

if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mWidth = MeasureSpec.getSize(widthMeasureSpec);

}

//2.获取高

if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mHeight = MeasureSpec.getSize(heightMeasureSpec);

}

//2. 确定宽高

setMeasuredDimension(mWidth, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//1 确定文字外框区域

Rect bounds = new Rect();

String str = "100.00%";

mTextPaint.getTextBounds(str, 0, str.length(), bounds);

int boxWidth = bounds.width() + sp2px(5);

int boxHeight = bounds.height() + sp2px(10);

int outWidth = (int)(mCurrentNum/mMaxNum * (mWidth-boxWidth)); //计算当前进度距离

drawBox(canvas, outWidth, boxWidth, boxHeight); //绘制外框

//2 画文字

Paint.FontMetricsInt metrics = mTextPaint.getFontMetricsInt();

int dy = (metrics.bottom - metrics.top) / 2 - metrics.bottom;

int baseLine = boxHeight / 2 + dy; //基线

//文字变化的时候 为了保证文字居中 所以需要知道文字区域大小

Rect bound = new Rect();

mTextPaint.getTextBounds(mText, 0, mText.length(), bound); //获取文字区域大小

canvas.drawText(mText, outWidth + (boxWidth/2 - bound.width()/2), baseLine, mTextPaint);

//3. 画进度条

//方式一:推荐

drawHLine(canvas, boxWidth/2, (boxHeight+sp2px(mTriangleValue)),mWidth, mHeight, mInPaint); //画内线

drawHLine(canvas, boxWidth/2, (boxHeight+sp2px(mTriangleValue)),boxWidth/2 + outWidth, mHeight, mOutPaint); //画外线

//方式一:不推荐

// int lineHeight = mHeight-boxHeight-sp2px(mTriangleValue);

// drawInLine(canvas, boxWidth/2, mWidth - boxWidth/2, lineHeight, mInPaint); //画内线

// drawOutLine(canvas, boxWidth/2, boxWidth/2 + outWidth, lineHeight, mOutPaint); //画外线

}

/**

* @param canvas

* @param left 左边距离

* @param width 矩形 宽

* @param height 矩形 高

*/

public void drawBox(Canvas canvas, int left, int width, int height){

//2.1 画圆角矩形

RectF rectF = new RectF(left, 0, width + left, height);// 设置个新的长方形

canvas.drawRoundRect(rectF, height/4, height/4, mBoxPaint);//第二个参数是x半径,第三个参数是y半径

//2.2 画三角形 (绘制这个三角形,你可以绘制任意多边形)

Path path = new Path();

path.moveTo(left + width/2-sp2px(4), height);// 此点为多边形的起点

path.lineTo(left + width/2+sp2px(4), height);

path.lineTo(left + width/2, height + sp2px(5));

path.close(); // 使这些点构成封闭的多边形

canvas.drawPath(path, mBoxPaint);

}

/**

* 水平进度条(前进方向平的) 通用

* @param canvas

* @param left

* @param top

* @param right

* @param bottom

* @param paint

*/

public void drawHLine(Canvas canvas, int left, int top, int right, int bottom, Paint paint){

int height = bottom - top; //高度

int r = height/2; //半径

int cFirstX = left + r; //第一个分割点x坐标

int cSecondX = mWidth - left - r; //第二个分割点x坐标

int cy = top + r; //圆心y坐标

//1. 绘制第一个圆

canvas.save();

canvas.clipRect(new RectF(left, top, right, bottom));

canvas.drawCircle(left+r, cy, r, paint);

canvas.restore();

//2. 绘制中间矩形

if(right >= cFirstX){

canvas.save();

int currentRight = right;

if(right > cSecondX){

currentRight = cSecondX;

}

canvas.drawRect(new RectF(left+r, top, currentRight, bottom), paint);

canvas.restore();

}

//3. 绘制最后的圆

if(right >= cSecondX){

canvas.save();

canvas.clipRect(new RectF(cSecondX, top, right, bottom));

canvas.drawCircle(cSecondX, cy, r, paint);

canvas.restore();

}

}

public void drawInLine(Canvas canvas, int left, int width, int height, Paint paint){

RectF rectF = new RectF(left, mHeight-height, width, mHeight); // 设置个新的长方形

canvas.drawRoundRect(rectF, height/2, height/2, paint); //第二个参数是x半径,第三个参数是y半径

}

//进度前进方向为圆角

public void drawOutLine(Canvas canvas, int left, int width, int height, Paint paint){

if((width-left) >= height){ //绘制圆角方式

RectF rectF = new RectF(left, mHeight-height, width, mHeight); // 设置个新的长方形

canvas.drawRoundRect(rectF, height/2, height/2, paint); //第二个参数是x半径,第三个参数是y半径

}

//绘制前面圆

RectF rectF = new RectF(left, mHeight-height, width, mHeight);

canvas.clipRect(rectF);

int r = height/2;

canvas.drawCircle(left+r, mHeight-height+r, r, paint);

}

private int sp2px(int sp) {

return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,

getResources().getDisplayMetrics());

}

public void setCurrentNum(double currentNum) {

this.mCurrentNum = currentNum;

if(mCurrentNum > mMaxNum){

mCurrentNum = mMaxNum;

}

mText = new DecimalFormat("0.00%").format(mCurrentNum/mMaxNum);

invalidate();

}

}

/**

* 水平进度条(带文字)

* @author liys 401654546@qq.com

* @version 1.0 2018/09/12

*/

public class HorzTextProgressView extends View{

private double mMaxNum = 10000; //最大值

private double mCurrentNum = 0; //当前的值

private String mText = "0%"; //当前 百分比

private int mTextSize; //字体大小

private int mTextColor = 0; //字体颜色

private int mInLineColor = 0; //内线颜色

private int mOutLineColor = 0; //外线颜色

private int mInLineSize; //外线 大小 单位sp

private int mOutLineSize; //内线 大小 单位sp

private int mWidth; //宽

private int mHeight; //高

private int mDefaultWidth = 300; //默认宽,单位sp

private int mDefaultHeight = 20; //默认高,单位sp

int boxWidth = 30; //文字框 宽 单位sp

//画笔

private Paint mTextPaint;

private Paint mInPaint;

private Paint mOutPaint;

private Paint mBoxPaint;

public HorzTextProgressView(Context context) {

this(context, null);

}

public HorzTextProgressView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs,0);

}

public HorzTextProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

//默认值

int defaultTextSize = 10; //默认字体大小 单位sp

String defaultTextColor = "#FFFFFF"; //默认字体颜色

String defaultInColor = "#EDEDED"; //默认内颜色

String defaultOutColor = "#CCBD00"; //默认外颜色

int defaultLineSize = 10; //默认线的大小 单位sp

// 获取自定义属性

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorzTextProgressView);

mText = typedArray.getString(R.styleable.HorzTextProgressView_liys_progress_horz_text);

mTextColor = typedArray.getColor(R.styleable.HorzTextProgressView_liys_progress_horz_textColor, Color.parseColor(defaultTextColor));

mInLineColor = typedArray.getColor(R.styleable.HorzTextProgressView_liys_progress_horz_inLineColor, Color.parseColor(defaultInColor));

mOutLineColor = typedArray.getColor(R.styleable.HorzTextProgressView_liys_progress_horz_outLineColor, Color.parseColor(defaultOutColor));

mTextSize = typedArray.getDimensionPixelSize(R.styleable.HorzTextProgressView_liys_progress_horz_textSize, sp2px(defaultTextSize));

mInLineSize = typedArray.getDimensionPixelSize(R.styleable.HorzTextProgressView_liys_progress_horz_inLineSize, sp2px(defaultLineSize));

mOutLineSize = typedArray.getDimensionPixelSize(R.styleable.HorzTextProgressView_liys_progress_horz_outLineSize, sp2px(defaultLineSize));

typedArray.recycle();

setTextPaint();

setInPaint();

setOutPaint();

setBoxPaint();

if(mText == null){

mText = "0%";

}

boxWidth = sp2px(boxWidth);

}

/**

* 方框画笔

*/

private void setBoxPaint() {

mBoxPaint = new Paint();

mBoxPaint.setAntiAlias(true);

mBoxPaint.setColor(mOutLineColor);

}

/**

* 文字画笔

*/

private void setTextPaint() {

mTextPaint = new Paint();

mTextPaint.setAntiAlias(true);

mTextPaint.setColor(mTextColor);

mTextPaint.setTextSize(mTextSize);

}

/**

* 内线画笔

*/

private void setInPaint() {

mInPaint = new Paint();

mInPaint.setAntiAlias(true);

mInPaint.setColor(mInLineColor);

mInPaint.setStrokeWidth(mInLineSize); //大小

mInPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

/**

* 外线画笔

*/

private void setOutPaint() {

mOutPaint = new Paint();

mOutPaint.setAntiAlias(true);

mOutPaint.setColor(mOutLineColor);

mOutPaint.setStrokeWidth(mOutLineSize); //大小

mOutPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//取默认值

mWidth = sp2px(mDefaultWidth);

mHeight = sp2px(mDefaultHeight);

//1. 获取宽

if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mWidth = MeasureSpec.getSize(widthMeasureSpec);

}

//2.获取高

if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mHeight = MeasureSpec.getSize(heightMeasureSpec);

}

//2. 确定宽高

setMeasuredDimension(mWidth, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//1. 获取当前进度

int outWidth = (int)(mCurrentNum/mMaxNum * mWidth); //计算当前进度距离

if(outWidth >= mWidth - boxWidth){

outWidth = (mWidth - boxWidth);

}

//2. 画进度条

int inTop = (mHeight - mInLineSize)/2;

int outTop = (mHeight - mOutLineSize)/2;

drawHLine(canvas, 0, inTop, mWidth, mHeight - inTop, mInPaint); //画内线

drawHLine(canvas, 0, outTop, outWidth+sp2px(2), mHeight - outTop, mOutPaint); //画外线

//3. 画文字框

drawBox(canvas, outWidth, boxWidth, mHeight);

//4. 画文字

Paint.FontMetricsInt metrics = mTextPaint.getFontMetricsInt();

int dy = (metrics.bottom - metrics.top) / 2 - metrics.bottom;

int baseLine = mHeight/2 + dy; //基线

//文字变化的时候 为了保证文字居中 所以需要知道文字区域大小

Rect bound = new Rect();

mTextPaint.getTextBounds(mText, 0, mText.length(), bound); //获取文字区域大小

canvas.drawText(mText, outWidth + (boxWidth/2 - bound.width()/2), baseLine, mTextPaint);

}

/**

* @param canvas

* @param left 左边距离

* @param width 矩形 宽

* @param height 矩形 高

*/

public void drawBox(Canvas canvas, int left, int width, int height){

RectF rectF = new RectF(left, 0, width + left, height); // 设置个新的长方形

canvas.drawRoundRect(rectF, height/2, height/2, mBoxPaint); //第二个参数是x半径,第三个参数是y半径

}

/**

* 水平进度条(前进方向平的) 通用

* @param canvas

* @param left

* @param top

* @param right

* @param bottom

* @param paint

*/

public void drawHLine(Canvas canvas, int left, int top, int right, int bottom, Paint paint){

int height = bottom - top; //高度

int r = height/2; //半径

int cFirstX = left + r; //第一个分割点x坐标

int cSecondX = mWidth - left - r; //第二个分割点x坐标

int cy = top + r; //圆心y坐标

//1. 绘制第一个圆

canvas.save();

canvas.clipRect(new RectF(left, top, right, bottom));

canvas.drawCircle(left+r, cy, r, paint);

canvas.restore();

//2. 绘制中间矩形

if(right >= cFirstX){

canvas.save();

int currentRight = right;

if(right > cSecondX){

currentRight = cSecondX;

}

canvas.drawRect(new RectF(left+r, top, currentRight, bottom), paint);

canvas.restore();

}

//3. 绘制最后的圆

if(right >= cSecondX){

canvas.save();

canvas.clipRect(new RectF(cSecondX, top, right, bottom));

canvas.drawCircle(cSecondX, cy, r, paint);

canvas.restore();

}

}

private int sp2px(int sp) {

return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,

getResources().getDisplayMetrics());

}

public void setCurrentNum(double currentNum) {

this.mCurrentNum = currentNum;

if(mCurrentNum > mMaxNum){

mCurrentNum = mMaxNum;

}

mText = new DecimalFormat("0%").format(mCurrentNum/mMaxNum);

invalidate();

}

}

**

* liys 2019-01-13

* 水平进度条(不带文字)

*/

public class HorzProgressView extends View{

private double mMaxNum = 100; //最大值

private double mCurrentNum = 0; //当前的值

private int mInLineColor = 0; //内线颜色

private int mOutLineColor = 0; //外线颜色

private Drawable mInLineDrawable = null; //内线图片

private Drawable mOutLineDrawable = null; //外线图片

private int mOutLineSize; //外线 大小 单位sp

private int mWidth; //宽

private int mHeight; //高

//画笔

private Paint mInPaint;

private Paint mOutPaint;

private Paint mPaint = new Paint(); //绘制图片

public HorzProgressView(Context context) {

this(context, null);

}

public HorzProgressView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs,0);

}

public HorzProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

// 获取自定义属性

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorzProgressView);

mCurrentNum = typedArray.getInteger(R.styleable.HorzProgressView_liys_progress_line_progress, 0);

mMaxNum = typedArray.getInteger(R.styleable.HorzProgressView_liys_progress_line_max, 100);

//颜色

mInLineColor = typedArray.getColor(R.styleable.HorzProgressView_liys_progress_line_inColor, 0);

mOutLineColor = typedArray.getColor(R.styleable.HorzProgressView_liys_progress_line_outColor, 0);

//图片

mInLineDrawable = typedArray.getDrawable(R.styleable.HorzProgressView_liys_progress_line_inDrawable);

mOutLineDrawable = typedArray.getDrawable(R.styleable.HorzProgressView_liys_progress_line_outDrawable);

//大小

mOutLineSize = typedArray.getDimensionPixelSize(R.styleable.HorzProgressView_liys_progress_line_outSize, 0);

typedArray.recycle();

setInPaint();

setOutPaint();

}

/**

* 内线画笔

*/

private void setInPaint() {

mInPaint = new Paint();

mInPaint.setAntiAlias(true);

mInPaint.setColor(mInLineColor);

mInPaint.setStrokeWidth(mHeight); //大小

mInPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

/**

* 外线画笔

*/

private void setOutPaint() {

mOutPaint = new Paint();

mOutPaint.setAntiAlias(true);

mOutPaint.setColor(mOutLineColor);

mOutPaint.setStrokeWidth(mOutLineSize); //大小

mOutPaint.setStrokeCap(Paint.Cap.ROUND); // 结束位置圆角

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//1. 获取宽

if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mWidth = MeasureSpec.getSize(widthMeasureSpec);

}

//2.获取高

if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mHeight = MeasureSpec.getSize(heightMeasureSpec);

}

if(mOutLineSize == 0){

mOutLineSize = mHeight;

}

//2. 确定宽高

setMeasuredDimension(mWidth, mHeight);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//内层

if(mInLineColor != 0){

drawInLine(canvas, 0, mWidth, mHeight, mInPaint); //画内线

}

if(mInLineDrawable != null){

Bitmap bitmap = ((BitmapDrawable) mInLineDrawable).getBitmap();

canvas.drawBitmap(bitmap, null, new Rect(0,0, mWidth, mHeight), mPaint);

}

//外层

int left = (mHeight-mOutLineSize)/2;

int width = (int)((mWidth-left)*(mCurrentNum/mMaxNum));

if(mOutLineColor != 0){

drawOutLine(canvas, left, width, mOutLineSize, mOutPaint); //画外线

}

if(mOutLineDrawable != null){

Bitmap bitmap = ((BitmapDrawable) mOutLineDrawable).getBitmap();

canvas.drawBitmap(bitmap, null, new Rect(left,(mHeight-mOutLineSize)/2, width, mOutLineSize), mPaint);

}

}

public void drawInLine(Canvas canvas, int left, int width, int height, Paint paint){

RectF rectF = new RectF(left, mHeight-height, width, mHeight); // 设置个新的长方形

canvas.drawRoundRect(rectF, height/2, height/2, paint); //第二个参数是x半径,第三个参数是y半径

}

/**

* 进度前进方向为圆角

*/

public void drawOutLine(Canvas canvas, int left, int width, int height, Paint paint){

int top = (mHeight-height)/2;

if((width-left) >= height){ //绘制圆角方式

// RectF rectF = new RectF(left, mHeight-height, width, mHeight); // 设置个新的长方形

RectF rectF = new RectF(left, top, width, mHeight-top); // 设置个新的长方形

canvas.drawRoundRect(rectF, height/2, height/2, paint); //第二个参数是x半径,第三个参数是y半径

}

//绘制前面圆

RectF rectF = new RectF(left, top, width, mHeight-top);

canvas.clipRect(rectF);

int r = height/2;

canvas.drawCircle(left+r, top+r, r, paint);

}

public void setMax(double max){

this.mMaxNum = max;

invalidate();

}

public void setCurrentNum(double currentNum) {

this.mCurrentNum = currentNum;

if(mCurrentNum > mMaxNum){

mCurrentNum = mMaxNum;

}

invalidate();

}

}

/**

* 水波进度条

* @author liys 401654546@qq.com

* @version 1.0 2018/09/12

*/

public class WaterWaveProView extends View {

private double mMaxNum = 10000; //最大值

private double mCurrentNum = 0; //当前的值

private double mPercent = 0.0; //百分比

private String mText = ""; //当前 百分比

private int mTextSize; //字体大小

private int mTextColor; //字体大小

private int mInColor = 0; //里面颜色

private int mWaterColor = 0; //水波颜色

//控件宽高

private int mWidth;

private int mHeight;

int mDefaultWidthHeight= 100; //默认宽高,单位sp

private float mStartX = 0; //开始位置

private int mWaveWidth; //水波长

private int mWaveHeight; //水波高度

private Paint mPaint;

private Paint mTextPaint;

private Path mPath;

public WaterWaveProView(Context context) {

this(context, null);

}

public WaterWaveProView(Context context, @Nullable AttributeSet attrs) {

this(context, attrs, 0);

}

public WaterWaveProView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

setLayerType(View.LAYER_TYPE_SOFTWARE, null);//关闭硬件加速

//默认值

int defaultTextSize = 20; //默认字体大小 单位sp

String defaultTextColor = "#FFFFFF"; //默认字体颜色

String defaultInColor = "#69B655"; //默认里面颜色

String defaultWaterColor = "#0AA328"; //默认水波颜色

// 获取自定义属性

TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.WaterWaveProView);

mText = typedArray.getString(R.styleable.WaterWaveProView_liys_progress_water_text);

mTextSize = typedArray.getDimensionPixelSize(R.styleable.WaterWaveProView_liys_progress_water_textSize, sp2px(defaultTextSize));

mTextColor = typedArray.getColor(R.styleable.WaterWaveProView_liys_progress_water_textColor, Color.parseColor(defaultTextColor));

mWaterColor = typedArray.getColor(R.styleable.WaterWaveProView_liys_progress_water_waterColor, Color.parseColor(defaultInColor));

mInColor = typedArray.getColor(R.styleable.WaterWaveProView_liys_progress_water_inColor, Color.parseColor(defaultWaterColor));

typedArray.recycle();

mPaint = new Paint();

mPaint.setAntiAlias(true);

mPaint.setColor(mWaterColor);

mTextPaint = new Paint();

mTextPaint.setAntiAlias(true);

mTextPaint.setColor(mTextColor);

mTextPaint.setTextSize(mTextSize);

mPath = new Path();

if(mText == null){

mText = "0.00%";

}

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int defaultWaterHeight = 5; //默认水波高度 单位sp

//1.取默认宽高

mWidth = sp2px(mDefaultWidthHeight);

mHeight = sp2px(mDefaultWidthHeight);

//2. 获取宽

if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mWidth = MeasureSpec.getSize(widthMeasureSpec);

}

//3.获取高

if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) { //具体值

mHeight = MeasureSpec.getSize(heightMeasureSpec);

}

//4. 确定宽高(保持宽高一致)

mWidth = mHeight = (mWidth > mHeight ? mHeight : mWidth);

//5. 确定波长和波高

mWaveWidth = mWidth/4;

mWaveHeight = sp2px(defaultWaterHeight);

setMeasuredDimension(mWidth, mHeight);

start();

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//1. 绘制贝塞尔曲线

drawBessel(mWidth, mStartX, (int)(mHeight*(1-mPercent)), mWaveWidth, mWaveHeight, mPath, mPaint);

canvas.drawPath(mPath, mPaint);

//2. 设置模式

mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));

//3. 绘制圆形bitmap

canvas.drawBitmap(createCircleBitmap(mWidth/2, mInColor), null, new Rect(0,0,mWidth,mHeight), mPaint);

//4. 绘制文字

drawText(canvas, mText, mWidth, mHeight, mTextPaint);

}

/**

* 绘制贝塞尔曲线

* @param width 总共需要绘制的长度

* @param startX 开始X点坐标(-2*startX 到 0 之间) 左右预留一个波长

* @param startY 开始Y坐标

* @param waveWidth 波长(半个周期)

* @param waveHeight 波高

* @param path

* @param paint 画笔

*/

private void drawBessel(float width, float startX, float startY, float waveWidth, float waveHeight, Path path, Paint paint){

//Android贝塞尔曲线

// 二阶写法:rQuadTo(float dx1, float dy1, float dx2, float dy2) 相对上一个起点的坐标

path.reset();

int currentWidth = 0; //当前已经绘制的宽度

path.moveTo(startX,startY); //画笔位置

while (currentWidth <= width + 4*waveWidth && waveWidth>0){

path.rQuadTo(waveWidth, -waveHeight, 2*waveWidth, 0);

path.rQuadTo(waveWidth, waveHeight, 2*waveWidth, 0);

currentWidth += 2*waveWidth;

}

//封闭的区域

mPath.lineTo(getWidth()+4*waveWidth,getHeight());

mPath.lineTo(0,getHeight());

path.close();

}

private Bitmap createCircleBitmap(int radius, int color){

Bitmap canvasBmp = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);

Canvas canvas = new Canvas(canvasBmp);

canvas.drawColor(Color.TRANSPARENT);

Paint paint = new Paint();

paint.setColor(color);

canvas.drawCircle(radius, radius, radius, paint); //确定位置

return canvasBmp;

}

/**

* 绘制文字 居中

* @param canvas

* @param text 文字内容

* @param width 绘制区域 宽

* @param height 绘制区域 高

* @param paint

*/

public void drawText(Canvas canvas, String text, int width, int height, Paint paint){

Rect bounds = new Rect();

paint.getTextBounds(text,0, mText.length(), bounds);

Paint.FontMetricsInt metrics = paint.getFontMetricsInt();

int dy = (metrics.bottom - metrics.top) / 2 - metrics.bottom;

int baseLine = height / 2 + dy; //基线

canvas.drawText(text, width/2-bounds.width()/2, baseLine, paint);

}

/**

* 设置当前进度

* @param currentNum

*/

public void setCurrentNum(double currentNum) {

this.mCurrentNum = currentNum;

setPercent();

}

public void setMaxNum(int maxNum){

this.mMaxNum = maxNum;

setPercent();

}

private void setPercent(){

if(mCurrentNum > mMaxNum){

mCurrentNum = mMaxNum;

}

mPercent = mCurrentNum/mMaxNum;

mText = new DecimalFormat("0.00%").format(mPercent);

}

private void setStartX(float startX){

mStartX = startX;

invalidate();

}

private int sp2px(int sp) {

return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,

getResources().getDisplayMetrics());

}

private void start(){

ValueAnimator animator = ValueAnimator.ofFloat(0-4*mWaveWidth, 0);

animator.setInterpolator(new LinearInterpolator());//匀速插值器 解决卡顿问题

animator.setDuration(2000);

animator.setRepeatCount(ValueAnimator.INFINITE);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

setStartX((float) animation.getAnimatedValue());

}

});

animator.start();

}

}

android 第三方圆弧进度条,Android 圆弧进度条 水平进度条 水波进度条相关推荐

  1. Android 第三方库--2017年Android开源项目及库汇总

    转自:http://blog.csdn.net/jsonnan/article/details/62215287 东西有点多,但是资源绝对nice,自己都全部亲身体验过了,大家可放心使用 github ...

  2. android第三方打开office文件,Android应用集成Office文件能力完全攻略

    Android应用打开office和pdf文件.常用的有以下四种解决方案: 在线网页打开文件方案:通过微软或谷歌提供的在线页面打开office和pdf文件 集成相关文档处理开源库:通过集成开源库类似于 ...

  3. android 画圆弧动画,『Android自定义View实战』自定义带入场动画的弧形百分比进度条...

    写在前面 这是在简书发表的处女座,这个想法也停留在脑海中很久了,一直拖到现在(懒癌发作2333),先自我介绍一番,一枚刚毕业不久的Android程序猿,初出茅庐的Android小生,之前一直在CSDN ...

  4. android第三方开源音频播放器,Android第三方开源SeekBarCompat:音乐类播放器等APP进度条常用...

     Android第三方开源SeekBarCompat:音乐类播放器等APP进度条常用 Android平台原生的SeekBar设计简单,然而,比如现在流行的一些音乐播放器的播放进度控制条,如果直接使 ...

  5. Android可触摸圆形进度条,Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动...

    Android 可滚动圆形进度条 滑块和进度在进度条上面跟着滚动.package com.example.test; import android.content.Context; import an ...

  6. android按钮进度动画,android – 在按钮后面放置一个进度条

    要做到这一点,我必须首先在main.xml中定义按钮,然后是进度条,如下所示: android:id="@+id/search_button" android:layout_wid ...

  7. android欢迎页圆形倒计时,android 欢迎页圆形进度条倒计时功能

    常见app欢迎页圆形进度条倒计时功能,可设置显示文字,进度条颜色,宽度,倒计时时间,内圆颜色.设置进度条类型  顺数进度条(0-100)还是倒数进度条(100-0): 先上效果图: 下面介绍实现逻辑: ...

  8. Android自定义滑动进度条,Android自定义View实现圆形水波进度条

    每次听到某大牛谈论自定义View,顿时敬佩之心,如滔滔江水连绵不绝,心想我什么时候能有如此境界,好了,心动不如行动,于是我开始了自定义View之路,虽然过程有坎坷,但是结果我还是挺满意的.我知道大牛还 ...

  9. android触摸进度条,Android仿IOS ViewPager滑动进度条

    最近做项目,碰到如下的需求:ViewPager分页,如果是6页(包括6页)就用圆点,如果是6页以上就用进度条来切换.前面一种交互方法最常见,用小圆点来表示当前选中的页面,这些小圆点称为导航点,很多Ap ...

  10. android 反向进度条,Android ProgressBar 反向进度条/进度条从右到左走

    最近的项目,有个需求需要使用条状图显示比例,并且右对齐,见下图: 我想到了使用进度条,这样不就不需要在代码动态绘制条状了,省了很多活. 那么进度条怎样从右向左显示呢? 方案一: 将ProgressBa ...

最新文章

  1. python应用实例论文_番外篇——Python多进程应用实例一则
  2. 理解Windows中的路由表和默认网关
  3. java 抽象类 方法_java 抽象类
  4. Cortex-M3复位序列
  5. sql实现从两个表获取字段组成表数据再插入到函数表中
  6. 58 - 算法 - 百练 2503:Babelfish 二分查找与存储
  7. asp.net core3.0 mvc 用 autofac
  8. [Java] 获取当前Project所在的路径
  9. 在mdk使用swd最后一步无反应_STM32应用笔记: 使用STM32CubeMonitor实时监测变量
  10. 更改PPT的模板名称
  11. html下拉选择图片,图片+JavaScript+CSS打造漂亮的select下拉选择框
  12. 【语义分割】一文概览主要语义分割网络,FCN、UNet、SegNet、DeepLab
  13. linux质控命令,RNA-seq摸索:2.sra下载数据→fastqc质控→hisat2/bowtie2/STAR/salmon比对→Samtools格式转换→IGV可视化结果...
  14. [转]冬天上厕所,马桶太冷怎么办?
  15. 【云和恩墨大讲堂】赴春天第一场约会,深圳等你
  16. 基于springboot的工资管理系统
  17. 盛金公式(一元三次方程的解)
  18. 指南解读:急性心力衰竭中国急诊管理指南(2022)
  19. 关于Application.DoEvents()
  20. 华为MateBook X Pro 2022和2021区别 哪个好

热门文章

  1. 汇编语言 王爽 【第四版】实验一
  2. 【Matlab系列】基于matlab的数字信号处理实验平台设计
  3. HTML特殊字符转义
  4. Java 登录拦截器
  5. 电信无线服务器的密码是什么,电信光猫wifi默认密码是多少?
  6. AndroidTV开发7实现仿小米电视和各种盒子TV焦点放大缩小效果
  7. JAVA人脸识别(人脸对比)
  8. java编程入门到精通课后答案,附源代码
  9. tableau学生版注册流程
  10. 如何批量删除Excel工作簿中vba代码