先看效果图
1.自定义的控件
public class CircleBarView extends View { private OnAnimationListener onAnimationListener; private TextView textView; private float sweepAngle;//圆弧经过的角度 private Paint rPaint;//绘制矩形的画笔 private Paint progressPaint;//绘制圆弧的画笔 CircleBarAnim anim; private Paint bgPaint;//绘制背景圆弧的画笔 private float progressNum;//可以更新的进度条数值 private float maxNum;//进度条最大值 private float progressSweepAngle;//进度条圆弧扫过的角度 private float startAngle;//背景圆弧的起始角度 private RectF mRectF;//绘制圆弧的矩形区域 private float barWidth;//圆弧进度条宽度 private int defaultSize;//自定义View默认的宽高 private int progressColor;//进度条圆弧颜色 private int bgColor;//背景圆弧颜色 public CircleBarView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } private void init(Context context, AttributeSet attrs) { rPaint = new Paint(); rPaint.setStyle(Paint.Style.STROKE);//只描边,不填充 rPaint.setColor(Color.RED); progressPaint = new Paint(); progressPaint.setStyle(Paint.Style.STROKE);//只描边,不填充 progressPaint.setColor(Color.BLUE); progressPaint.setAntiAlias(true);//设置抗锯齿 anim = new CircleBarAnim(); progressPaint = new Paint(); progressPaint.setStyle(Paint.Style.STROKE);//只描边,不填充 progressPaint.setColor(Color.GREEN); progressPaint.setAntiAlias(true);//设置抗锯齿 progressPaint.setStrokeWidth(15);//随便设置一个画笔宽度,看看效果就好,之后会通过attr自定义属性进行设置 bgPaint = new Paint(); bgPaint.setStyle(Paint.Style.STROKE);//只描边,不填充 bgPaint.setColor(Color.GRAY); bgPaint.setAntiAlias(true);//设置抗锯齿 bgPaint.setStrokeWidth(15); progressNum = 0; maxNum = 100;//也是随便设的 startAngle = 0; sweepAngle = 360; defaultSize = dip2px(context, 100); barWidth = dip2px(context, 10); mRectF = new RectF(); progressPaint.setStrokeWidth(barWidth); bgPaint.setStrokeWidth(barWidth); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleBarView); progressColor = typedArray.getColor(R.styleable.CircleBarView_progress_color, Color.GREEN);//默认为绿色 bgColor = typedArray.getColor(R.styleable.CircleBarView_bg_color, Color.GRAY);//默认为灰色 startAngle = typedArray.getFloat(R.styleable.CircleBarView_start_angle, 0);//默认为0 sweepAngle = typedArray.getFloat(R.styleable.CircleBarView_sweep_angle, 360);//默认为360 barWidth = typedArray.getDimension(R.styleable.CircleBarView_bar_width, dip2px(context, 10));//默认为10dp typedArray.recycle();//typedArray用完之后需要回收,防止内存泄漏 progressPaint.setColor(progressColor); progressPaint.setStrokeWidth(barWidth); bgPaint.setColor(bgColor); bgPaint.setStrokeWidth(barWidth); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float x = 50; float y = 50; RectF rectF = new RectF(x, y, x + 300, y + 300);//建一个大小为300 * 300的正方形区域 canvas.drawArc(mRectF,startAngle,sweepAngle,false,bgPaint); canvas.drawArc(mRectF,startAngle,progressSweepAngle,false, progressPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int height = measureSize(defaultSize, heightMeasureSpec); int width = measureSize(defaultSize, widthMeasureSpec); int min = Math.min(width, height);// 获取View最短边的长度 setMeasuredDimension(min, min);// 强制改View为以最短边为长度的正方形 if (min >= barWidth * 2) {//这里简单限制了圆弧的最大宽度 mRectF.set(barWidth / 2, barWidth / 2, min - barWidth / 2, min - barWidth / 2); } } private int measureSize(int defaultSize, int measureSpec) { int result = defaultSize; int specMode = View.MeasureSpec.getMode(measureSpec); int specSize = View.MeasureSpec.getSize(measureSpec); if (specMode == View.MeasureSpec.EXACTLY) { result = specSize; } else if (specMode == View.MeasureSpec.AT_MOST) { result = Math.min(result, specSize); } return result; } public class CircleBarAnim extends Animation { public CircleBarAnim() { } @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); sweepAngle = interpolatedTime * 360; progressSweepAngle = interpolatedTime * sweepAngle * progressNum / maxNum;//这里计算进度条的比例 postInvalidate(); if(textView !=null&& onAnimationListener!=null){ textView.setText(onAnimationListener.howToChangeText(interpolatedTime,progressNum,maxNum)); } } } //写个方法给外部调用,用来设置动画时间 public void setProgressNum(float progressNum, int time) { anim.setDuration(time); this.startAnimation(anim); this.progressNum = progressNum; } public int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } public int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } /** * 设置显示文字的TextView * @param textView */ public void setTextView(TextView textView) { this.textView = textView; } public interface OnAnimationListener { /** * 如何处理要显示的文字内容 * @param interpolatedTime 从0渐变成1,到1时结束动画 * @param progressNum 进度条数值 * @param maxNum 进度条最大值 * @return */ String howToChangeText(float interpolatedTime, float progressNum, float maxNum); } }
2.attr.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <!--注意这里的name要和自定义View的名称一致,不然在布局文件中无法引用--> <declare-styleable name="CircleBarView"> <attr name="progress_color" format="color"></attr> <attr name="bg_color" format="color"></attr> <attr name="bar_width" format="dimension"></attr> <attr name="start_angle" format="float"></attr> <attr name="sweep_angle" format="float"></attr> </declare-styleable> </resources>
3.布局使用
<RelativeLayout android:layout_width="100dp" android:layout_height="100dp" android:layout_marginTop="10dp" android:layout_marginRight="50dp"> <com.qikeya.qkyxt.widgets.CircleBarView android:id="@+id/circle_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center_horizontal" app:bar_width="8dp" app:bg_color="#FFB9DEFF" app:progress_color="#FFFFFFFF" app:start_angle="-90" app:sweep_angle="270" /> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/text_gailv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="正确率" android:textColor="@color/white" android:textSize="12sp" /> <TextView android:id="@+id/text_progres" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="23%" android:textColor="@color/white" android:textSize="25sp" android:textStyle="bold" /> </LinearLayout> </RelativeLayout>
4. java代码
circle_view.setProgressNum(23,1500); text_progress.setText("23%");
多谢大神https://blog.csdn.net/lly347705530/article/details/78213501的博客 让我解决了这个难题