android 进度条控制,Android 球形进度条,动态控制时间与最大进度

老规矩,先上效果图:

9df41d1ab5b4c7825116f03bba2033d1.png

1.我直接写好了一个自定义View类,直接贴代码:

import android.animation.ValueAnimator;

import android.content.Context;

import android.graphics.Canvas;

import android.graphics.Color;

import android.graphics.Paint;

import android.graphics.Path;

import android.graphics.Point;

import android.graphics.Rect;

import android.support.annotation.Nullable;

import android.util.AttributeSet;

import android.util.Log;

import android.view.View;

import android.view.animation.LinearInterpolator;

/**

* Author: ManitZhang

* Date: 2018/5/20

* email: manitozhang@foxmail.com

* 球形进度条

*/

public class CircleProgress extends View {

//View的宽高

private int width;

private int height;

//View的画笔

private Paint wavePaint;

private Paint textPaint;

private Paint circlePaint;

//波浪的路径

private Path path;

//sin曲线的长度:一个周期长度

private int cycle = 100;

//每次平移的长度,为四分之一个周期

private int translateX = cycle / 5;

//sin曲线振幅的高度

private int waveHeight = 20;

//sin曲线的起点坐标

private Point startPoint;

//当前波浪的进度

private int progress = 0;

//当前波浪的速度

private int waveSpeech = 80;

//是否启用了自动增长进度

private boolean isAutoIncrease = false;

protected OnCircleProgressListener onCircleProgressListener;

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

super(context, attrs);

initPaint(context);

}

public CircleProgress(Context context) {

super(context);

initPaint(context);

}

private void initPaint(Context context) {

path = new Path();

wavePaint = new Paint();

wavePaint.setAntiAlias(true);

wavePaint.setStyle(Paint.Style.FILL);

wavePaint.setColor(Color.parseColor("#FBE201"));

circlePaint = new Paint();

circlePaint.setStrokeWidth(5);

circlePaint.setStyle(Paint.Style.STROKE);

circlePaint.setAntiAlias(true);

circlePaint.setColor(Color.parseColor("#FBE201"));

textPaint = new Paint();

textPaint.setAntiAlias(true);

textPaint.setTextSize(50);

textPaint.setColor(Color.WHITE);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

//由于是一个圆形,所以取的值是宽高的最小值

width = measureSize(400, widthMeasureSpec);

height = measureSize(400, heightMeasureSpec);

width = Math.min(width, height);

height = Math.min(width, height);

setMeasuredDimension(width, height);

//初始化起点,为屏幕外的一个周期

startPoint = new Point(-cycle * 4, 0);

}

/**

* 测量宽高

*

* @param defaultSize

* @param measureSpec

* @return

*/

private int measureSize(int defaultSize, int measureSpec) {

int result = defaultSize;

int mode = MeasureSpec.getMode(measureSpec);

int size = MeasureSpec.getSize(measureSpec);

switch (mode) {

case MeasureSpec.UNSPECIFIED:

result = defaultSize;

break;

case MeasureSpec.AT_MOST:

case MeasureSpec.EXACTLY:

result = size;

break;

}

return result;

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

//设置内间距

setPadding(20, 20, 20, 20);

//裁剪画布为圆形

clipCicle(canvas);

//绘制圆形边框

drawCicleBorder(canvas);

//绘制波浪区域

drawWavePath(canvas);

//绘制进度文字

drawProcessText(canvas);

//自动增长进度

if (isAutoIncrease) {

if (progress >= 100) {

progress = 0;

} else {

progress++;

}

}

//更新UI

postInvalidateDelayed(waveSpeech);

}

/**

* 裁剪画布为圆形

*

* @param canvas

*/

private void clipCicle(Canvas canvas) {

Path circlePath = new Path();

circlePath.addCircle(width / 2, height / 2, width / 2, Path.Direction.CW);

canvas.clipPath(circlePath);

}

/**

* 绘制圆形边框

*

* @param canvas

*/

private void drawCicleBorder(Canvas canvas) {

canvas.drawPaint(circlePaint);

canvas.drawCircle(width / 2, height / 2, width / 2, circlePaint);

}

/**

* 绘制波浪区域

*

* @param canvas

*/

private void drawWavePath(Canvas canvas) {

//根据进度改变起点坐标的y值

startPoint.y = (int) ((1 - (progress / 100.0)) * (height / 2 + width / 2));

Log.e("TAG", "startPoint.y:" + startPoint.y);

//移动区域起点

path.moveTo(startPoint.x, startPoint.y);

int j = 1;

//循环绘制正弦曲线区域,循环两个周期

for (int i = 1; i <= 8; i++) {

if (i % 2 == 0) {

//波峰

path.quadTo(startPoint.x + (cycle * j), startPoint.y + waveHeight,

startPoint.x + (cycle * 2) * i, startPoint.y);

} else {

//波谷

path.quadTo(startPoint.x + (cycle * j), startPoint.y - waveHeight,

startPoint.x + (cycle * 2) * i, startPoint.y);

}

j += 2;

}

//绘制封闭的区域

path.lineTo(width, height);//右下角

path.lineTo(startPoint.x, height);//左下角

path.lineTo(startPoint.x, startPoint.y);//起点

path.close();

//绘制区域

canvas.drawPath(path, wavePaint);

path.reset();

//一开始的起点是在-160,160 = 40 + 40 + 40 + 40,走完一个周期则回到原点

if (startPoint.x + translateX >= 0) {

startPoint.x = -cycle * 4;

} else {

startPoint.x += translateX;

}

}

/**

* 绘制进度文字

*

* @param canvas

*/

private void drawProcessText(Canvas canvas) {

//画布的大小

Rect targetRect = new Rect(0, 0, width, height);

Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt();

int baseline = (targetRect.bottom + targetRect.top - fontMetrics.bottom - fontMetrics.top) / 2;

// 下面这行是实现水平居中,drawText对应改为传入targetRect.centerX()

textPaint.setTextAlign(Paint.Align.CENTER);

canvas.drawText(progress + "%", targetRect.centerX(), baseline, textPaint);

onCircleProgressListener.OnCircleProgress(progress);

}

/**

* 定义一个接口监听进度

*/

public interface OnCircleProgressListener{

boolean OnCircleProgress(int progress);

}

public void setOnCircleProgressListener(OnCircleProgressListener onCircleProgressListener) {

this.onCircleProgressListener = onCircleProgressListener;

}

/**

* 开启自动增长

*/

public void startIncrease() {

isAutoIncrease = true;

invalidate();

}

/**

* 设置当前进度

*

* @param progress 进度

*/

public void setProgress(int progress) {

if (progress > 100 || progress < 0)

throw new RuntimeException(getClass().getName() + "请设置[0,100]之间的值");

this.progress = progress;

invalidate();

}

/**

* 通过动画设置当前进度

*

* @param targetProcess 进度 <=100

* @param duration 动画时长

*/

public void setProgress(final int targetProcess, int duration) {

if (progress > 100 || progress < 0)

throw new RuntimeException(getClass().getName() + "请设置[0,100]之间的值");

ValueAnimator progressAnimator = ValueAnimator.ofInt(progress, targetProcess);

progressAnimator.setDuration(duration);

progressAnimator.setTarget(progress);

progressAnimator.setInterpolator(new LinearInterpolator());

progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

setProgress((Integer) animation.getAnimatedValue());

}

});

progressAnimator.start();

}

/**

* 获取当前进度

*

* @return

*/

public int getProgress() {

return progress;

}

}

2.我们在布局调用这个写好的自定义View:

3.然后我们就可以直接在MainActivity调用这个自定义View了:

import android.support.v7.app.AppCompatActivity;

import android.os.Bundle;

import android.view.View;

import android.widget.Button;

public class MainActivity extends AppCompatActivity {

private CircleProgress mCpLoading;

private Button mBtnLoading;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mCpLoading = findViewById(R.id.cp_loading);//自定义View

mBtnLoading = findViewById(R.id.btn_loading);//按钮

//按钮点击

mBtnLoading.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

mCpLoading.setProgress(100,5000);

}

});

//我在自定义View写了一个接口回调,来监听进度

mCpLoading.setOnCircleProgressListener(new CircleProgress.OnCircleProgressListener() {

@Override

public boolean OnCircleProgress(int progress) {

if(progress==100){

mCpLoading.setProgress(0);

}

return false;

}

});

}

}

4.到这里我们就已经完成了,如果看着不合适的或者波动较小或

者较大,可以自己在自定义View里面调节值,如果有不懂的可以

问我

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值