效果图:
ArcCircleView控件
package com.example.myapplicationfortest;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.util.AttributeSet;
import android.view.View;
import com.android.settings.R;
public class ArcCircleView extends View {
private Context mContext;
/**
* 文本画笔
*/
private Paint mTextPaint;
/**
* 圆弧画笔
*/
private Paint mArcCirclePaint;
/**
* 圆形进度条宽度
*/
private float mWidth = 100.0f;
/**
* 进度条中显示的文本
*/
private String mText ="";
/**
* 弧度
*/
private int mAngleValue = 0;
/**
* 圆的背景色:默认浅绿色
*/
private int mCircleBackgroundColor = 0x4c11af9c;
/**
* 进度的颜色,默认白色
*/
private int mProgressColor = 0xffffffff;
/**
* 文本的颜色,默认白色
*/
private int mTextColor = 0xffffffff;
/**
* 边宽
*/
private float mStrokeWidth = 8;
/**
* 进度圆边宽
*/
private float mInnerStrokeWidth = 7;
/**
* 文本大小
*/
private float mTextSize = 12;
public ArcCircleView(Context context) {
super(context);
init(context);
}
public ArcCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.ArcCircleViewStyle);
mWidth = a.getDimension(R.styleable.ArcCircleViewStyle_circleWidth,0);
mStrokeWidth = a.getDimension(R.styleable.ArcCircleViewStyle_strokeWidth,0);
mInnerStrokeWidth = a.getDimension(R.styleable.ArcCircleViewStyle_innerStrokeWidth,0);
mTextSize = a.getDimension(R.styleable.ArcCircleViewStyle_textSize, 0);
init(context);
setProgress(0);
}
public ArcCircleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context){
mContext = context;
mTextPaint = new Paint();
//设置抗锯齿
mTextPaint.setAntiAlias(true);
//使文本看起来更清晰
mTextPaint.setLinearText(true);
mArcCirclePaint = new Paint();
mArcCirclePaint.setAntiAlias(true);
// 设置画笔为描边模式
mArcCirclePaint.setStyle(Paint.Style.STROKE);
}
public void setWidth(float width){
mWidth = width;
invalidate();
}
public void setText(String text){
mText = text;
invalidate();
}
public void setTextColor(int textColor) {
this.mTextColor = mContext.getResources().getColor(textColor);
invalidate();
}
public void setCircleBackgroundColor(int circleBackgroundColor) {
this.mCircleBackgroundColor = mContext.getResources().getColor(circleBackgroundColor);
invalidate();
}
public void setStrokeWidth(float strokeWidth){
this.mStrokeWidth = strokeWidth;
invalidate();
}
public void setInnerStrokeWidth(float innerStrokeWidth){
this.mInnerStrokeWidth = innerStrokeWidth;
invalidate();
}
public void setTextSize(float textSize){
this.mTextSize = textSize;
invalidate();
}
/**
* 设置进度
* @param progress
*/
public void setProgress(float progress){
int angleValue = (int) ((progress * 1.0)/100 * 360);
if (angleValue > 0 && progress <= 100){
mAngleValue = angleValue;
mText = String.valueOf(progress)+"%";
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 圆弧的位置:整圆,再绘制进度圆弧
mArcCirclePaint.setColor(mCircleBackgroundColor);
mArcCirclePaint.setStrokeWidth(mStrokeWidth);
// 获取整个组件的宽度
int width = getMeasuredWidth();
// 获取整个组件的高度
int height = getMeasuredHeight();
RectF rectF = new RectF();
// mStrokeWidth 是为使进度条不显示到控件外
rectF.left = (width - mWidth + mStrokeWidth)/2;//左上角X
rectF.top = (height - mWidth + mStrokeWidth)/2;//左上角Y
rectF.right = (width + mWidth - mStrokeWidth)/2;//右上角X
rectF.bottom = (height + mWidth - mStrokeWidth)/2;//右上角Y
//第2个参数:时钟3点处为0度, 所以顺时针旋转270度表示从顶部开始画进度
canvas.drawArc(rectF, 270, 360, false, mArcCirclePaint);
mArcCirclePaint.setColor(mProgressColor);
//设置边角为圆
mArcCirclePaint.setStrokeCap(Paint.Cap.ROUND);
mArcCirclePaint.setStrokeWidth(mInnerStrokeWidth);
canvas.drawArc(rectF, 270, mAngleValue, false, mArcCirclePaint);
// 设置画笔属性
mTextPaint.setColor(mTextColor);
mTextPaint.setTextSize(mTextSize);
// 需要先设置画笔的textsize大小后才能通过measureText 函数获取准确的宽度
int textWidth = (int) mTextPaint.measureText(mText, 0, mText.length());
// 文本的位置:居中显示
int textX = (width - textWidth)/2;
//计算baseline:垂直方向居中
int baseline = (int)((getMeasuredHeight() - (mTextPaint.descent() - mTextPaint.ascent())) / 2 - mTextPaint.ascent());
canvas.drawText(mText, textX, baseline, mTextPaint);
}
}
页面布局文件:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="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:orientation="vertical"
android:background="@android:color/holo_blue_bright"
tools:context=".MainActivity">
<TextView
android:id="@+id/text_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:text="Hello World!" />
<com.mobiletek.myapplicationfortest.ArcCircleView
android:id="@+id/progress_circular"
android:layout_width="match_parent"
android:layout_height="300dp"
android:padding="30dp"
app:circleWidth="200dp"
app:strokeWidth="14dp"
app:innerStrokeWidth="13dp"
app:topTextSize="30sp"
app:textSize="45sp"/>
<Button
android:id="@+id/start_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="开始"/>
<Button
android:id="@+id/stop_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="暂停"/>
</LinearLayout>
主页面代码如下:MainActivity.java
package com.example.myapplicationfortest;
public class MainActivity extends AppCompatActivity {
private ArcCircleView processBar;
private Button startBtn;
private Button stopBtn;
public static int count = 0;
public boolean canRunning = true;
Handler handler=new Handler();
Runnable runnable=new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
//要做的事情,这里再次调用此Runnable对象,以实现每0.1秒实现一次的定时器操作
if (canRunning && count <= 100) {
processBar.setProgress(count++);
handler.postDelayed(this, 100);
} else if (count > 100) {
processBar.setProgress(count = 0);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
processBar = findViewById(R.id.progress_circular);
startBtn = findViewById(R.id.start_btn);
startBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
canRunning = true;
handler.post(runnable);
}
});
stopBtn = findViewById(R.id.stop_btn);
stopBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
canRunning = false;
}
});
}
}