通过效果图,我们首先抽象出自定义属性,如下:
圆环内部填充色。
圆环进度条的背景色。
圆环进度条的颜色。
圆环半径。
圆环进度条的宽度。
进度条起始的角度。
中间文字的颜色。
中间文字的大小。
中间文字是否需要显示的标志位。
在Android中,可以在项目的res/values/目录下,建立一个resources源文件,通过declare-styleable来声明一个特定的属性集合。
示例属性集合如下所示(res/values/attrs_round_progress_bar.xml):
<resources><declare-styleable name="RoundProgressBar"><attr name="startAngle" format="integer"></attr><attr name="radius" format="dimension"></attr><attr name="ringWidth" format="dimension"></attr><attr name="centerColor" format="color"></attr><attr name="ringColor" format="color"></attr><attr name="progressColor" format="color"></attr><attr name="textSize" format="dimension"></attr><attr name="textColor" format="color"></attr><attr name="isTextDisplay" format="boolean"></attr></declare-styleable></resources>自定义的属性可以在自定义View的构造函数中,通过TypedArray数组获取,我们来自定义一个圆形的View来实现上图的效果(RoundProgressBar.java):
package love.com.progressbar.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.RectF;import android.graphics.Typeface;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import love.com.progressbar.R;public class RoundProgressBar extends View {private static final int START_ANGLE = -90;private static final String CENTER_COLOR = "#eeff06";private static final String RING_COLOR = "#FF7281E1";private static final String PROGRESS_COLOR = "#FFDA0F0F";private static final String TEXT_COLOR = "#FF000000";private static final int TEXT_SIZE = 30;private static final int CIRCLE_RADIUS = 20;private static final int RING_WIDTH = 5;/** * 圆弧的起始角度,参考canvas.drawArc方法 */private int startAngle;/** * 圆形内半径 */private int radius;/** * 进度条的宽度 */private int ringWidth;/** * 默认进度 */private int mProgress = 0;/** * 圆形内部填充色 */private int centerColor;/** * 进度条背景色 */private int ringColor;/** * 进度条的颜色 */private int progressColor;/** * 文字大小 */private int textSize;/** * 文字颜色 */private int textColor;/** * 文字是否需要显示 */private boolean isTextDisplay;private String textContent;private Paint mPaint;public RoundProgressBar(Context context) {this(context, null);}public RoundProgressBar(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RoundProgressBar(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);// 获取自定义属性TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressBar);for (int i = 0; i < a.length(); i ++) {int attr = a.getIndex(i);switch (attr) {case R.styleable.RoundProgressBar_startAngle:startAngle = a.getInteger(attr, START_ANGLE);break;case R.styleable.RoundProgressBar_centerColor:centerColor = a.getColor(attr, Color.parseColor(CENTER_COLOR));break;case R.styleable.RoundProgressBar_progressColor:progressColor = a.getColor(attr, Color.parseColor(PROGRESS_COLOR));break;case R.styleable.RoundProgressBar_ringColor:ringColor = a.getColor(attr, Color.parseColor(RING_COLOR));break;case R.styleable.RoundProgressBar_textColor:textColor = a.getColor(attr, Color.parseColor(TEXT_COLOR));break;case R.styleable.RoundProgressBar_textSize:textSize = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TEXT_SIZE,getResources().getDisplayMetrics()));break;case R.styleable.RoundProgressBar_isTextDisplay:isTextDisplay = a.getBoolean(attr, true);break;case R.styleable.RoundProgressBar_radius:radius = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CIRCLE_RADIUS,getResources().getDisplayMetrics()));break;case R.styleable.RoundProgressBar_ringWidth: ringWidth = (int) a.getDimension(attr, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, RING_WIDTH,getResources().getDisplayMetrics()));break;default:break;}}a.recycle();// 初始化画笔设置setPaint();}private void setPaint() {mPaint = new Paint();mPaint.setAntiAlias(true);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 获取圆心坐标int cx = getWidth() / 2;int cy = cx;/** * 画圆心颜色 */if (centerColor != 0) {drawCenterCircle(canvas, cx, cy);}/** * 画外层大圆 */drawOuterCircle(canvas, cx, cy);/** * 画进度圆弧 */drawProgress(canvas, cx, cy);/** * 画出进度百分比 */drawProgressText(canvas, cx, cy);}private void drawProgressText(Canvas canvas, int cx, int cy) {if (!isTextDisplay) {return;}mPaint.setColor(textColor);mPaint.setTextSize(textSize);mPaint.setTypeface(Typeface.DEFAULT_BOLD);mPaint.setStrokeWidth(0);textContent = getProgress() + "%";float textWidth = mPaint.measureText(textContent);canvas.drawText(textContent, cx - textWidth / 2, cy + textSize / 2, mPaint);}private void drawProgress(Canvas canvas, int cx, int cy) {mPaint.setColor(progressColor);mPaint.setStrokeWidth(ringWidth);mPaint.setStyle(Paint.Style.STROKE);RectF mRectF = new RectF(cx - radius, cy - radius, cx + radius, cy + radius);float sweepAngle = (float) (mProgress * 360.0 / 100);canvas.drawArc(mRectF, startAngle, sweepAngle, false, mPaint);}private void drawOuterCircle(Canvas canvas, int cx, int cy) {mPaint.setStyle(Paint.Style.STROKE);mPaint.setColor(ringColor);mPaint.setStrokeWidth(ringWidth);canvas.drawCircle(cx, cy, radius, mPaint);}private void drawCenterCircle(Canvas canvas, int cx, int cy) {mPaint.setColor(centerColor);mPaint.setStyle(Paint.Style.FILL);canvas.drawCircle(cx, cy, radius, mPaint);}public synchronized int getProgress() {return mProgress;}public synchronized void setProgress(int progress) {if (progress < 0) {progress = 0;} else if (progress > 100) {progress = 100;}mProgress = progress;// 进度改变时,需要通过invalidate方法进行重绘postInvalidate();}}在MainActivity.java的布局文件中,可以这样调用圆形进度条:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:round="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><love.com.progressbar.view.RoundProgressBarandroid:id="@+id/id_round_progressbar"android:layout_width="400dp"android:layout_height="400dp"round:radius="100dp"round:ringWidth="20dp"round:startAngle="-90"round:centerColor="#eeff06"round:ringColor="#e16556e6"round:progressColor="#d20c0c"round:textColor="#000000"round:textSize="20sp"round:isTextDisplay="true"/></RelativeLayout>其中,xmlns:round=”http://schemas.android.com/apk/res-auto是Android Studio中增加的导入自定义View属性的命名空间写法。