Android自定义圆形进度条,效果图如下:
主要逻辑如下:
RoundProgressBar.java
package com.jackie.roundprogressbar; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; import android.view.View; /** * 仿iphone带进度的进度条,线程安全的View,可直接在线程中更新进度 * @author Jackie * */ public class RoundProgressBar extends View { private Paint mPaint; //画笔对象 private int mRoundColor; //圆环的颜色 private int mRoundProgressColor; //圆形进度的颜色 private int mTextColor; //中间进度百分比的字符串的颜色 private float mTextSize; //中间进度百分比的字符串的字体 private float mRoundWidth; //圆环的宽度 private float mProgress; //当前进度 private int mMax; //最大进度 private boolean mTextIsDisplayable; //是否显示中间的进度 private int mStyle; //进度的风格,实心或者空心 private static final int STROKE = 0; private static final int FILL = 1; public RoundProgressBar(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(); TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar); //获取自定义属性和默认值 mRoundColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundColor, Color.RED); mRoundProgressColor = mTypedArray.getColor(R.styleable.RoundProgressBar_roundProgressColor, Color.GREEN); mTextColor = mTypedArray.getColor(R.styleable.RoundProgressBar_textRColor, Color.GREEN); mTextSize = mTypedArray.getDimension(R.styleable.RoundProgressBar_textRSize, 15); mRoundWidth = mTypedArray.getDimension(R.styleable.RoundProgressBar_roundWidth, 5); mMax = mTypedArray.getInteger(R.styleable.RoundProgressBar_max, 100); mTextIsDisplayable = mTypedArray.getBoolean(R.styleable.RoundProgressBar_textIsDisplayable, true); mStyle = mTypedArray.getInt(R.styleable.RoundProgressBar_style, 0); mTypedArray.recycle(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //画最外层的大圆环 int center = getWidth() / 2; //获取圆心的x坐标 int radius = (int) (center - mRoundWidth / 2); //圆环的半径 mPaint.setColor(mRoundColor); //设置圆环的颜色 mPaint.setStyle(Paint.Style.STROKE); //设置空心 mPaint.setStrokeWidth(mRoundWidth); mPaint.setAntiAlias(true); //消除据此 canvas.drawCircle(center, center, radius, mPaint); //画出圆环 //画进度百分比 mPaint.setStrokeWidth(0); mPaint.setColor(mTextColor); mPaint.setTextSize(mTextSize); mPaint.setTypeface(Typeface.DEFAULT); //设置字体 int percent = (int)(((float)mProgress / (float)mMax) * 100); //中间的进度百分比,先转换成float在进行除法运算,不然都为0 float textWidth = mPaint.measureText("PVideo"); //测量字体宽度,我们需要根据字体的宽度设置在圆环中间 if (mTextIsDisplayable && percent != 0 && mStyle == STROKE) { //画出进度百分比 canvas.drawText(" " + percent + "%", center - textWidth / 2, center + mTextSize / 2, mPaint); } //画圆弧,画圆环的进度 //设置进度是实心还是空心 mPaint.setStrokeWidth(mRoundWidth); //设置圆环的宽度 mPaint.setColor(mRoundProgressColor); //设置进度的颜色 RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius); //用于定义的圆弧的形状和大小的界限 switch(mStyle) { case STROKE: mPaint.setStyle(Paint.Style.STROKE); canvas.drawArc(oval, 0, 360 * mProgress / mMax, false, mPaint); break; case FILL: mPaint.setStyle(Paint.Style.FILL_AND_STROKE); if (mProgress != 0) { canvas.drawArc(oval, 0, 360 * mProgress/ mMax, true, mPaint); //根据进度画圆弧 } break; } } public synchronized int getMax() { return mMax; } /** * 设置进度的最大值 * @param max */ public synchronized void setMax(int max) { if(max < 0){ throw new IllegalArgumentException("Max not less than 0"); } this.mMax = max; } /** * 获取进度.需要同步 * @return */ public synchronized float getProgress() { return mProgress; } /** * 设置进度,此为线程安全控件,由于考虑多线程的问题,需要同步 * 刷新界面调用postInvalidate()能在非UI线程刷新 * @param progress */ public synchronized void setProgress(float progress) { if (progress < 0) { throw new IllegalArgumentException("Progress not less than 0"); } if (progress > mMax) { progress = mMax; } if (progress <= mMax) { this.mProgress = progress; postInvalidate(); if (progress == mMax && mListener != null) { mListener.onFinished(true); } else if (mListener != null) { mListener.onCurrentPercent(mMax, (int)progress); } } } private OnProgressListener mListener; public void setOnProgressLister(OnProgressListener listener) { this.mListener = listener; } public interface OnProgressListener { public void onFinished(boolean result); public void onCurrentPercent(int mTotalTime , int mCurrentTime); } public void setTextSize(float textSize) { this.mTextSize = textSize; } public void setRoundWidth(float roundWidth) { this.mRoundWidth = roundWidth; } }MainActivity.java
package com.jackie.roundprogressbar; import com.jackie.roundprogressbar.RoundProgressBar.OnProgressListener; import android.app.Activity; import android.os.Bundle; import android.os.Handler; public class MainActivity extends Activity implements OnProgressListener { private RoundProgressBar mRoundProgressBar; private Handler mHandler = new Handler(); private int mProgress = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mRoundProgressBar = (RoundProgressBar) findViewById(R.id.roundprogressbar); mRoundProgressBar.setOnProgressLister(this); mRoundProgressBar.setTextSize(100); mRoundProgressBar.setRoundWidth(50); mHandler.postDelayed(mRunnable, 0); } private Runnable mRunnable = new Runnable() { @Override public void run() { mRoundProgressBar.setProgress(mProgress); mProgress += 5; mHandler.postDelayed(this, 1000); } }; @Override public void onFinished(boolean result) { mHandler.removeCallbacks(mRunnable); } @Override public void onCurrentPercent(int mTotalTime, int mCurrentTime) { } }