自定义圆形进度条(旋转进度+百分比)
欢迎大家批评指正
效果如下
转载请注明:https://blog.****.net/jinchen_boke/article/details/80546871,谢谢。
代码如下:
import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.View; /** * Created by lenovo on 2018/3/16. */ public class CircleProgreessView extends View { //控件宽高 private float mWidth; private float mHeight; //画笔 private Paint mPaint; //中间的文本 private String text = "0%";//测试用 private float strokeWidth = 10f; //圆圈的宽度 private float textSize = 40f;//中间文本的大小 private int textColor = Color.RED;//中间文本的颜色 private int bgCircleColor = Color.GREEN;//背景圆圈的颜色 private int progressCircleColor = Color.BLUE;//进度圆圈的颜色 //当前进度 private int mProgress; //旋转的动画 private ValueAnimator animator; public CircleProgreessView(Context context) { this(context,null); } public CircleProgreessView(Context context, @Nullable AttributeSet attrs) { this(context, attrs,0); } public CircleProgreessView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { if(null == mPaint){ mPaint = new Paint(); mPaint.setAntiAlias(true); //消除锯齿 mPaint.setTextSize(textSize); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画布移动到控件中央,以控件中心为圆心 canvas.translate(mWidth/2,mHeight/2); //测量文本的宽和高 Rect textRect = new Rect(); mPaint.getTextBounds(text,0, text.length(),textRect); int textHeight = textRect.height(); int textWidth = textRect.width(); //设置为填充样式 mPaint.setStyle(Paint.Style.FILL); //设置中间的文本颜色 mPaint.setColor(textColor); //已经以控件中心为原点,画文本的时候这里传入的位置是文本的左下角的位置, //所以要传入-textWidth/2 ,textHeight/2 修正一下 //画中间的文本 canvas.drawText(text,-textWidth/2 ,textHeight/2,mPaint); //设置 圆圈 样式为空心,这样才显示为圆圈 mPaint.setStyle(Paint.Style.STROKE); //设置 背景圆圈 的颜色 mPaint.setColor(bgCircleColor); //环带宽度,圆宽度,边线宽度 mPaint.setStrokeWidth(strokeWidth); //画 背景圆圈 canvas.drawCircle(0,0,mHeight/2 - strokeWidth /2,mPaint); if(mProgress != 0){ //画 进度圆圈 mPaint.setColor(progressCircleColor); //画 进度圆圈,因为画弧线的时候,是以弧线的中线到边界,如果用于画圈的矩形去掉 strokeWidth /2 //那在内切的地方 就会有1/2的弧线是看不到的,所以矩形的四个边要收缩 1/2边线的宽度 canvas.drawArc(new RectF( -mWidth/2+ strokeWidth /2, -mHeight/2+ strokeWidth /2, mWidth/2- strokeWidth /2, mHeight/2- strokeWidth /2), 180,//从左侧开始画,逆时针从右侧旋转180到左侧,开始画 360 * mProgress/100f,//进度,转换为度数 false,//画出的弧形,不封闭,否则会连接两端的半径进行封闭 mPaint); } //平移位置后恢复 canvas.restore(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mWidth = w; mHeight = h; } /** * 设置进度,设置后进度会从0到这个进度,会有一个动画,这个时间也可以传过来 * @param progress 0-100 * @param animationTime 动画时间,单位为毫秒 */ public void setProgress(int progress, int animationTime){ //this.mProgress = progress; startAnimator(progress,animationTime); } /** * 更新进度,如下载时可以调用这个方法,更新进度,不带动画 * @param progress 0-100 */ public void updateProgress(int progress){ //this.mProgress = progress; startAnimator(progress,0); } private void startAnimator(int value,int animationTime) { if(0 == animationTime){ mProgress = value; text = mProgress+"%"; invalidate(); }else { if(null != animator && animator.isRunning()){ animator.cancel(); } animator = ValueAnimator.ofInt(0, value); animator.setDuration(animationTime); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { /** * 通过这样一个监听事件,我们就可以获取 * 到ValueAnimator每一步所产生的值。 * 通过调用getAnimatedValue()获取到每个时间因子所产生的Value。 * */ Integer value = (Integer) animation.getAnimatedValue(); mProgress = value; text = mProgress+"%"; invalidate(); } }); animator.start(); } } }
测试代码如下:
Random random = new Random();
点击更新进度 执行如下方法: public void order(View view){ int precent = random.nextInt(100); if(precent == 0){ precent =1; } progressView.setProgress(precent,1000); //progressView.updateProgress(precent); }