效果图:
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/acad85c40778d8c4d29fc9bb86d1b043.jpeg)
自定义view:
import android.animation.FloatEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.BounceInterpolator;
public class HalfProgressView extends View {
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 300;
private Paint inner_progress_paint, outer_bg_paint, outer_progress_paint, inner_bg_paint;
private Paint top_text_paint, bottom_text1_paint, bottom_text2_paint;
private RectF inner_rect, outer_rect;
private Float value = 100F;
private int width;
private int height;
private String top_txt;
private String bottom_txt1;
private String bottom_txt2;
private float top_text_size;
private int topTextWidth;
private int bottomText1Width;
public HalfProgressView(Context context) {
super(context);
init();
}
public HalfProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public HalfProgressView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void init() {
inner_progress_paint = new Paint();
inner_progress_paint.setAntiAlias(true);
inner_progress_paint.setColor(Color.WHITE);
inner_progress_paint.setStyle(Style.STROKE);
inner_progress_paint.setStrokeCap(Paint.Cap.ROUND);
outer_bg_paint = new Paint();
outer_bg_paint.setAntiAlias(true);
outer_bg_paint.setColor(Color.parseColor("#c2edff"));
outer_bg_paint.setStyle(Style.STROKE);
outer_bg_paint.setStrokeCap(Paint.Cap.ROUND);
outer_progress_paint = new Paint();
outer_progress_paint.setAntiAlias(true);
outer_progress_paint.setColor(Color.WHITE);
outer_progress_paint.setStyle(Style.STROKE);
outer_progress_paint.setStrokeCap(Paint.Cap.ROUND);
inner_bg_paint = new Paint();
inner_bg_paint.setAntiAlias(true);
inner_bg_paint.setColor(Color.parseColor("#c2edff"));
inner_bg_paint.setStyle(Style.STROKE);
inner_bg_paint.setStrokeCap(Paint.Cap.ROUND);
top_text_paint = new Paint();
top_text_paint.setAntiAlias(true);
top_text_paint.setColor(Color.parseColor("#666666"));
bottom_text1_paint = new Paint();
bottom_text1_paint.setAntiAlias(true);
bottom_text1_paint.setColor(Color.parseColor("#ff0000"));
bottom_text1_paint.setTextAlign(Paint.Align.RIGHT);
bottom_text2_paint = new Paint();
bottom_text2_paint.setAntiAlias(true);
bottom_text2_paint.setColor(Color.parseColor("#ff0000"));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = getProperSize(DEFAULT_WIDTH, widthMeasureSpec);
int height = getProperSize(DEFAULT_HEIGHT, heightMeasureSpec);
int result = Math.min(width, height);
setMeasuredDimension(result, result);
}
private int getProperSize(int defaultSize, int measureSpec) {
int result;
int mode = MeasureSpec.getMode(measureSpec);
int size = MeasureSpec.getSize(measureSpec);
if (mode == MeasureSpec.EXACTLY) {
result = size;
} else {
result = defaultSize;
if (mode == MeasureSpec.AT_MOST) {
result = Math.min(result, size);
}
}
return result;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
float inner_stroke_width = h * 0.105f;
float outer_stroke_width = h * 0.017f;
inner_progress_paint.setStrokeWidth(inner_stroke_width);
outer_progress_paint.setStrokeWidth(outer_stroke_width);
outer_bg_paint.setStrokeWidth(outer_stroke_width);
inner_bg_paint.setStrokeWidth(inner_stroke_width);
top_text_size = h * 0.027f;
float bottom_text1_size = h * 0.052f;
float bottom_text2_size = h * 0.032f;
top_text_paint.setTextSize(dip2px(getContext(), top_text_size));
topTextWidth = (int) top_text_paint.measureText(top_txt);
bottomText1Width = (int) bottom_text1_paint.measureText(bottom_txt1);
bottom_text1_paint.setTextSize(dip2px(getContext(), bottom_text1_size));
bottom_text2_paint.setTextSize(dip2px(getContext(), bottom_text2_size));
float inner_circle_radius = h * 0.40f;
float outer_circle_radius = h * 0.48f;
float inner_start_y = h / 2 - inner_circle_radius;
float outer_start_y = h / 2 - outer_circle_radius;
LinearGradient inner_progress_shader = new LinearGradient(w / 2 - inner_circle_radius, inner_start_y,
w / 2 - inner_circle_radius + inner_circle_radius * 2, 0,
new int[]{Color.parseColor("#f50a0a"), Color.parseColor("#FFA500"), Color.parseColor("#fed947")},
null,
Shader.TileMode.CLAMP);
inner_progress_paint.setShader(inner_progress_shader);
LinearGradient outer_progress_shader = new LinearGradient(w / 2 - outer_circle_radius, outer_start_y,
w / 2 - outer_circle_radius + outer_circle_radius * 2, 0,
new int[]{Color.parseColor("#f50a0a"), Color.parseColor("#FFA500"), Color.parseColor("#fed947")},
null,
Shader.TileMode.CLAMP);
outer_progress_paint.setShader(outer_progress_shader);
inner_rect = new RectF(w / 2 - inner_circle_radius,
inner_start_y,
w / 2 - inner_circle_radius + inner_circle_radius * 2,
inner_start_y + inner_circle_radius * 2);
outer_rect = new RectF(w / 2 - outer_circle_radius,
outer_start_y,
w / 2 - outer_circle_radius + outer_circle_radius * 2,
outer_start_y + outer_circle_radius * 2);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawArc(outer_rect, 130, 280, false, outer_bg_paint);
canvas.drawArc(inner_rect, 130, 280, false, inner_bg_paint);
float sweepAngle = (280 * value / 100) == 0 ? 1f : (280 * value / 100);
canvas.drawArc(outer_rect, 130, sweepAngle, false, outer_progress_paint);
canvas.drawArc(inner_rect, 130, sweepAngle, false, inner_progress_paint);
canvas.drawLine(width / 2, 0, width / 2, height, top_text_paint);
canvas.drawText(top_txt, width / 2 - topTextWidth / 2, height / 2 - top_text_size * 5, top_text_paint);
canvas.drawText(bottom_txt1, width / 2 - bottomText1Width / 2 + (int) (top_text_size * 1.5), height / 2 + top_text_size * 6, bottom_text1_paint);
canvas.drawText(bottom_txt2, width / 2 - bottomText1Width / 2 + (int) (top_text_size * 1.5), height / 2 + top_text_size * 6, bottom_text2_paint);
}
public void start(int progress) {
final ValueAnimator valueAnimator = ValueAnimator.ofObject(new FloatEvaluator(), 0, progress);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
value = (Float) animation.getAnimatedValue();
postInvalidate();
}
});
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new BounceInterpolator());
valueAnimator.start();
}
public void setTopTop(String top_txt) {
this.top_txt = top_txt;
invalidate();
}
public void setBottomLeftTxt(String bottom_txt1) {
this.bottom_txt1 = bottom_txt1;
invalidate();
}
public void setBottomRightTxt(String bottom_txt2) {
this.bottom_txt2 = bottom_txt2;
invalidate();
}
private static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<example.com.myping.HalfProgressView
android:id="@+id/half_progress1"
android:layout_width="30dp"
android:layout_height="30dp" />
<example.com.myping.HalfProgressView
android:id="@+id/half_progress2"
android:layout_width="60dp"
android:layout_height="60dp" />
<example.com.myping.HalfProgressView
android:id="@+id/half_progress3"
android:layout_width="90dp"
android:layout_height="90dp" />
<example.com.myping.HalfProgressView
android:id="@+id/half_progress4"
android:layout_width="120dp"
android:layout_height="120dp" />
<example.com.myping.HalfProgressView
android:id="@+id/half_progress5"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
String top_txt = "当前进度";
String bottom_txt1;
String bottom_txt2 = "00%";
HalfProgressView half_progress1 = (HalfProgressView) findViewById(R.id.half_progress1);
half_progress1.setTopTop(top_txt);
bottom_txt1 = "10.";
half_progress1.setBottomLeftTxt(bottom_txt1);
half_progress1.setBottomRightTxt(bottom_txt2);
half_progress1.start(10);
HalfProgressView half_progress2 = (HalfProgressView) findViewById(R.id.half_progress2);
half_progress2.setTopTop(top_txt);
bottom_txt1 = "40.";
half_progress2.setBottomLeftTxt(bottom_txt1);
half_progress2.setBottomRightTxt(bottom_txt2);
half_progress2.start(40);
HalfProgressView half_progress3 = (HalfProgressView) findViewById(R.id.half_progress3);
half_progress3.setTopTop(top_txt);
bottom_txt1 = "60.";
half_progress3.setBottomLeftTxt(bottom_txt1);
half_progress3.setBottomRightTxt(bottom_txt2);
half_progress3.start(60);
HalfProgressView half_progress4 = (HalfProgressView) findViewById(R.id.half_progress4);
half_progress4.setTopTop(top_txt);
bottom_txt1 = "80.";
half_progress4.setBottomLeftTxt(bottom_txt1);
half_progress4.setBottomRightTxt(bottom_txt2);
half_progress4.start(80);
HalfProgressView half_progress5 = (HalfProgressView) findViewById(R.id.half_progress5);
half_progress5.setTopTop(top_txt);
bottom_txt1 = "100.";
half_progress5.setBottomLeftTxt(bottom_txt1);
half_progress5.setBottomRightTxt(bottom_txt2);
half_progress5.start(100);
}
}