Android 圓形進度條
阿新 • • 發佈:2019-02-16
目錄結構
核心程式碼CicleProgressView.java
public class CircleProgressView extends View {
/**
* 背景顏色
*/
private int backgroundColor;
/**
* 前景顏色
*/
private int foregroundColor;
/**
* 進度條顏色
*/
private int progressColor;
/**
* 字型顏色
*/
private int fontColor;
/**
* 當前進度
*/
private int currentProgress = 0;
/**
* 最大進度
*/
private int maxProgress;
/**
* 畫筆
*/
private Paint mPaint = new Paint();
/**
* 半徑長
*/
private int mRadius;
/**
* 進度寬
*/
private int progressWidth;
/**
* 字型大小
*/
private int textSize;
/**
* 回撥監聽
*/
private ProgressedListener listener;
public CircleProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleProgressView);
backgroundColor = a.getColor(R.styleable.CircleProgressView_circleprogress_backgroundcolor, Color.WHITE);
foregroundColor = a.getColor(R.styleable.CircleProgressView_circleprogress_foregroundcolor, Color.WHITE);
progressColor = a.getColor(R.styleable.CircleProgressView_circleprogress_progresscolor, Color.BLUE);
fontColor = a.getColor(R.styleable.CircleProgressView_circleprogress_fontcolor, Color.BLUE);
maxProgress = a.getInteger(R.styleable.CircleProgressView_circleprogress_maxprogress, 100 );
progressWidth = a.getInteger(R.styleable.CircleProgressView_circleprogress_width, 10);
textSize = a.getInteger(R.styleable.CircleProgressView_circleprogress_textsize, 10);
a.recycle();//釋放資源
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
// int widthSize = MeasureSpec.getSize(widthMeasureSpec);
// int heightSize = MeasureSpec.getSize(heightMeasureSpec);
if (widthSpecMode == MeasureSpec.AT_MOST && heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(200, 200);
} else if (widthSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(heightMeasureSpec, heightMeasureSpec);
} else if (heightSpecMode == MeasureSpec.AT_MOST) {
setMeasuredDimension(widthMeasureSpec, widthMeasureSpec);
}
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > h) {
mRadius = h / 2;
} else {
mRadius = w / 2;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(backgroundColor);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, mRadius, mPaint);//畫最下邊的圓
mPaint.setColor(progressColor);
canvas.drawArc(getWidth() / 2 - mRadius,
getHeight() / 2 - mRadius,
getWidth() / 2 + mRadius,
getHeight() / 2 + mRadius,
-90,
360 * (((float) currentProgress) / maxProgress),
true,
mPaint);//畫扇形
mPaint.setColor(foregroundColor);
canvas.drawCircle(getWidth() / 2, getHeight() / 2,
mRadius - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, progressWidth, getResources().getDisplayMetrics()),
mPaint);//畫中心圓
mPaint.setColor(fontColor);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, textSize, getResources().getDisplayMetrics()));
String text = currentProgress + "%";
canvas.drawText(text,
getWidth() / 2 - mPaint.measureText(text) / 2,
getHeight() / 2 + mPaint.measureText("%") / 2,
mPaint);//畫文字
}
/**
* 設定當前進度
*
* @param currentProgress
*/
public void setCurrentProgress(int currentProgress) {
if (currentProgress <= 0) {
currentProgress = 0;
if (listener != null) {
listener.startLoad();
}
}
if (currentProgress >= maxProgress) {
currentProgress = maxProgress;
if (listener != null) {
listener.loadEnd();
}
}
this.currentProgress = currentProgress;
if (listener != null) {
listener.progressLoading(currentProgress);
}
invalidate();//重繪
}
public void setListener(ProgressedListener listener) {
this.listener = listener;
}
public interface ProgressedListener {
void loadEnd();//載入結束
void progressLoading(int progressed);//載入中
void startLoad();//開始載入
}
}
- 自定義屬性 attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircleProgressView">
<!-- 背景色-->
<attr name="circleprogress_backgroundcolor" format="color" />
<!-- 前景色-->
<attr name="circleprogress_foregroundcolor" format="color" />
<!-- 進度條顏色 -->
<attr name="circleprogress_progresscolor" format="color" />
<!-- 字型顏色-->
<attr name="circleprogress_fontcolor" format="color" />
<!-- 最大進度 -->
<attr name="circleprogress_maxprogress" format="integer" />
<!-- 進度寬 -->
<attr name="circleprogress_width" format="integer" />
<!-- 字型大小-->
<attr name="circleprogress_textsize" format="integer" />
</declare-styleable>
</resources>
- 佈局檔案 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:circleprogress="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.wxq.me.mycsdndemo.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.wxq.me.mycsdndemo.CircleProgressView
android:id="@+id/circle_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
circleprogress:circleprogress_backgroundcolor="#dddddd"
circleprogress:circleprogress_fontcolor="#0000ff"
circleprogress:circleprogress_foregroundcolor="#ffffff"
circleprogress:circleprogress_maxprogress="100"
circleprogress:circleprogress_progresscolor="#0000ff" />
<com.wxq.me.mycsdndemo.CircleProgressView
android:id="@+id/circle_view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
circleprogress:circleprogress_backgroundcolor="#000000"
circleprogress:circleprogress_fontcolor="#ff0000"
circleprogress:circleprogress_foregroundcolor="#ffffff"
circleprogress:circleprogress_maxprogress="100"
circleprogress:circleprogress_progresscolor="#ff0000"
circleprogress:circleprogress_textsize="20"
circleprogress:circleprogress_width="5" />
<com.wxq.me.mycsdndemo.CircleProgressView
android:id="@+id/circle_view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
circleprogress:circleprogress_backgroundcolor="#ff0000"
circleprogress:circleprogress_fontcolor="#ffff00"
circleprogress:circleprogress_foregroundcolor="#ffffff"
circleprogress:circleprogress_maxprogress="100"
circleprogress:circleprogress_progresscolor="#ffff00"
circleprogress:circleprogress_textsize="20"
circleprogress:circleprogress_width="5" />
</LinearLayout>
<com.wxq.me.mycsdndemo.CircleProgressView
android:id="@+id/circle_view3"
android:layout_width="match_parent"
android:layout_height="match_parent"
circleprogress:circleprogress_backgroundcolor="#dddddd"
circleprogress:circleprogress_fontcolor="#00ffff"
circleprogress:circleprogress_foregroundcolor="#ffffff"
circleprogress:circleprogress_maxprogress="100"
circleprogress:circleprogress_progresscolor="#00ffff"
circleprogress:circleprogress_textsize="50"
circleprogress:circleprogress_width="20" />
</LinearLayout>
- MainActivity.java
public class MainActivity extends AppCompatActivity {
private CircleProgressView mCircleProgressView, mCircleProgressView1, mCircleProgressView2, mCircleProgressView3;
private int currentProgress = 0;
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
if (currentProgress <= 100) {
mCircleProgressView.setCurrentProgress(currentProgress);
mCircleProgressView1.setCurrentProgress(currentProgress);
mCircleProgressView2.setCurrentProgress(currentProgress);
mCircleProgressView3.setCurrentProgress(currentProgress);
Log.i("wx", currentProgress + "");
currentProgress++;
sendEmptyMessageDelayed(1, 10);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mCircleProgressView = (CircleProgressView) findViewById(R.id.circle_view);
mCircleProgressView1 = (CircleProgressView) findViewById(R.id.circle_view1);
mCircleProgressView2 = (CircleProgressView) findViewById(R.id.circle_view2);
mCircleProgressView3 = (CircleProgressView) findViewById(R.id.circle_view3);
mCircleProgressView.setListener(new CircleProgressView.ProgressedListener() {
@Override
public void loadEnd() {
Toast.makeText(MainActivity.this, "載入結束", Toast.LENGTH_SHORT).show();
}
@Override
public void progressLoading(int progressed) {
//TODO
}
@Override
public void startLoad() {
Toast.makeText(MainActivity.this, "載入開始", Toast.LENGTH_SHORT).show();
}
});
mHandler.sendEmptyMessageDelayed(1, 1000);
}
}
實現思路
- 在onDraw方法中先中繪製外圓,再去繪製扇形,再繪製內圓,最後繪製文字。
- 在CircleProgressView定義介面ProgressedListener,MainActivity中實現這個介面,開始載入回撥startLoad方法,載入中回撥progressLoading方法,載入結束回撥loadEnd方法。
- 在MainActivity使用handler模擬進度載入呼叫setCurrentProgress方法。