先上效果圖
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* 自定義帶圓點的進度條
*/
public class HalfProgressBar extends View {
/**
* 當前進度
*/
private int progress = 150;
/**
* 最大進度
*/
private int maxProgress = 360;
//設定進度條背景寬度
private float progressStrokeWidth = 15;
//設定進度條進度寬度
// private float marxArcStorkeWidth = 6;
//設定進度條圓點的寬度
private float circularDotWidth = 30;
/**
* 畫筆物件的參照
*/
private Paint paintBackGround;
private Paint paintProgress;
private Paint paintDot;
private float progressTextSize;
public synchronized int getProgress() {
return progress;
}
/**
* Android提供了Invalidate方法實現介面重新整理,但是Invalidate不能直接線上程中呼叫,因為他是違背了單執行緒模型:Android UI操作並不是執行緒安全的,並且這些操作必須在UI執行緒中呼叫。
* 而postInvalidate()在工作者執行緒中被呼叫 使用postInvalidate則比較簡單,不需要handler,直接線上程中呼叫postInvalidate即可。
*
* @param progress 傳過來的進度
*/
public void setProgress(int progress) {
if (progress < 0) {
progress = 0;
}
if (progress > maxProgress) {
progress = maxProgress;
}
if (progress <= maxProgress) {
this.progress = progress;
postInvalidate();
}
}
private RectF oval;
private int roundProgressColor;
private int roundColor;
private int circularDotColor;
private int progressTextColor;
public HalfProgressBar(Context context) {
super(context);
}
public HalfProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public HalfProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
paintBackGround = new Paint();
paintProgress = new Paint();
paintDot = new Paint();
oval = new RectF();
//這是自定義view 必須要寫的
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.MyHalfProgressBar);
roundProgressColor = mTypedArray.getColor(R.styleable.MyHalfProgressBar_roundProgressColor1, Color.YELLOW);
roundColor = mTypedArray.getColor(R.styleable.MyHalfProgressBar_roundColor1, Color.YELLOW);
circularDotColor = mTypedArray.getColor(R.styleable.MyHalfProgressBar_circularDotColor1, Color.YELLOW);
progressTextSize = mTypedArray.getDimension(R.styleable.MyHalfProgressBar_progressTextSize, 15);
progressTextColor = mTypedArray.getInteger(R.styleable.MyHalfProgressBar_progressTextColor, Color.YELLOW);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float width = getWidth();
float height = getWidth();
paintBackGround.setAntiAlias(false); // 設定畫筆為抗鋸齒
paintBackGround.setColor(roundColor); // 設定畫筆顏色
paintBackGround.setStrokeWidth(progressStrokeWidth); // 線寬
paintBackGround.setStyle(Paint.Style.STROKE);
//進度條顏色
paintProgress.setColor(roundProgressColor);
paintProgress.setStrokeWidth(progressStrokeWidth);
paintProgress.setAntiAlias(false); // 設定畫筆為抗鋸齒
paintProgress.setStyle(Paint.Style.STROKE);
oval.left = circularDotWidth / 2; //
oval.top = circularDotWidth/2; //
oval.right = width - circularDotWidth / 2; //
oval.bottom = width - circularDotWidth / 2; //
float banjing = (width/2 - progressStrokeWidth / 2);//半徑
//調整圓背景的大小
canvas.drawArc(oval, 360, 360, false, paintBackGround); // 繪製紅絲圓圈,即進度條背景
Log.i("banjing",":"+banjing);
Log.i("banjing","width:"+width);
canvas.drawArc(oval, 180, progress, false, paintProgress); // 繪製進度圓弧,這裡是藍色
//畫圓點
paintDot.setColor(circularDotColor);
paintDot.setAntiAlias(true); // 設定畫筆為抗鋸齒
paintDot.setStyle(Paint.Style.FILL);
paintDot.setStrokeWidth(circularDotWidth);
//當畫筆樣式為STROKE或FILL_OR_STROKE時,設定筆刷的圖形樣式,如圓形樣式Cap.ROUND,或方形樣式Cap.SQUARE
paintDot.setStrokeCap(Paint.Cap.ROUND);
float jindu = ((float) progress * 1.7f);
double a=0;
float x=0;
float y=0;
float v=0;
float v1=0;
if (progress<90){
a = (Math.PI / (double) 180) * (90-progress);
v = (float) (Math.sin(a)) * banjing;
v1 = (float) (Math.cos(a)) * banjing;
x = width/2 + progressStrokeWidth / 2 - v;
y = width/2 + progressStrokeWidth / 2 - v1;
}
if (progress==90){
x = width/2 ;
y = circularDotWidth/2;
}
if (progress>90&&progress<180){
a = (Math.PI / (double) 180) * (180-progress);
v = (float) (Math.sin(a)) * banjing;
v1 = (float) (Math.cos(a)) * banjing;
if (progress>=150){
x = width/2 - progressStrokeWidth / 2 + v1;
y = width/2 - v;
}else {
x = width/2 + v1;
y = width/2 + progressStrokeWidth/2 - v;
}
}
if (progress==180){
x = width -progressStrokeWidth;
y = width/2;
}
if (progress>180&&progress<270){
a = (Math.PI / (double) 180) * (270-progress);
v = (float) (Math.sin(a)) * banjing;
v1 = (float) (Math.cos(a)) * banjing;
if (progress>=240){
x = width/2 - progressStrokeWidth / 2 + v;
y = width/2 - progressStrokeWidth / 2 + v1;
}else {
x = width/2 - progressStrokeWidth / 2 + v;
y = width/2 + v1;
}
}
if (progress==270){
// a = (Math.PI / (double) 180) * (270-progress);
// v = (float) (Math.sin(a)) * banjing;
// v1 = (float) (Math.cos(a)) * banjing;
x = width/2;
y = width - progressStrokeWidth ;
}
if (progress>270){
a = (Math.PI / (double) 180) * (360-progress);
v = (float) (Math.sin(a)) * banjing;
v1 = (float) (Math.cos(a)) * banjing;
x = width/2 + progressStrokeWidth / 2 - v1;
y = width/2 - progressStrokeWidth / 2 + v;
}
canvas.drawPoint(x, y, paintDot);
Log.i("banjing",",a:"+a);
Log.i("banjing",",x:"+x);
Log.i("banjing",",y:"+y);
Log.i("banjing",",v:"+v);
Log.i("banjing",",v1:"+v1);
//繪製中間文字
String testProgress =( (int)progress*100/360)+"%";
TextPaint mPaint = new TextPaint();
mPaint.setStrokeWidth(7);
mPaint.setTextSize(progressTextSize);
mPaint.setTypeface(Typeface.DEFAULT_BOLD);
mPaint.setColor(progressTextColor);
mPaint.setTextAlign(Paint.Align.LEFT);
Rect bounds = new Rect();
mPaint.getTextBounds(testProgress, 0, testProgress.length(), bounds);
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
canvas.drawText(testProgress,getMeasuredWidth() / 2 - bounds.width() / 2, baseline, mPaint);
}
}
<declare-styleable name="MyHalfProgressBar">
<attr name="roundColor1" format="color"/>
<attr name="roundProgressColor1" format="color"/>
<attr name="circularDotColor1" format="color"/>
<attr name="progressTextColor" format="color"/>
<attr name="progressTextSize" format="dimension"/>
</declare-styleable>
#44c8da
#4444c8da