自定义view-圆形进度条,效果图如下。
上代码,里面有详细注释。
1、创建 CircleProgressBar.java
public class CircleProgressBar extends View {
// 初始颜色画笔-灰色
private Paint grayPaint;
// 圆形变化画笔-粉红色
private Paint pinkPaint;
// 百分比文字画笔
private Paint textPaint;
private String progressText = "0"; // 记录百分比文字
private int strokeWidth = 10; // 圆弧边缘宽度
private int progress = 0; // 当前进度
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// 初始化默认画笔-白色
grayPaint = new Paint();
// 设置绘制图形的样式,填充(FILL)、描边(STROKE)
grayPaint.setStyle(Paint.Style.STROKE);
// 设置描边的宽度
grayPaint.setStrokeWidth(strokeWidth);
// 初始颜色为灰色
grayPaint.setColor(Color.GRAY);
// 开启抗锯齿
grayPaint.setAntiAlias(true);
// 初始化圆形变动颜色的画笔-粉色
pinkPaint = new Paint();
// 设置绘制图形的样式,填充(FILL)、描边(STROKE)
pinkPaint.setStyle(Paint.Style.STROKE);
// 设置描边的宽度
pinkPaint.setStrokeWidth(strokeWidth);
// 初始颜色为粉红色
pinkPaint.setColor(Color.parseColor("#FF69B4"));
// 开启抗锯齿
pinkPaint.setAntiAlias(true);
// 绘制进度条文字
textPaint = new Paint();
// 描边填充
textPaint.setStyle(Paint.Style.FILL);
// 红色
textPaint.setColor(Color.RED);
// 设置文字大小
textPaint.setTextSize(50);
// 设置文字对齐
textPaint.setTextAlign(Paint.Align.CENTER);
// 开启抗锯齿
textPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 获取 View 的中心坐标。例如宽度是263,结果是 263 / 2 = 131
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
// 计算圆形的半径,取视图宽高的最小值,并考虑边缘宽度。 半径126
int radius = Math.min(getWidth(), getHeight()) / 2 - strokeWidth / 2;
// 根据中心坐标和半径计算圆形的外接矩形区域
RectF rectF = new RectF(centerX - radius, centerY - radius, centerX + radius, centerY + radius);
// 画灰色的圆
canvas.drawArc(rectF, -90, 360, false, grayPaint);
// 画粉色的进度圆
int sweepAngle = (int) (360 * (progress / 100f));
canvas.drawArc(rectF, -90, sweepAngle, false, pinkPaint);
// 绘制百分比文字
int textX = getWidth() / 2;
int textY = getHeight() / 2 + getTextHeight() / 2;
canvas.drawText(progressText, textX, textY, textPaint);
}
/**
* 获取绘制文本的高度。
* 使用 textPaint 画笔测量进度文本的高度,以便在绘图时垂直居中文本。
* @return 文本的高度
*/
private int getTextHeight() {
// 创建一个矩形对象用于存储文本的边界
Rect textBounds = new Rect();
// 使用 textPaint 画笔测量进度文本的边界
textPaint.getTextBounds(progressText, 0, progressText.length(), textBounds);
// 返回文本的高度
return textBounds.height();
}
/**
* 增加进度
*/
public void increaseProgress(int progress) {
if (this.progress < 100) {
// 增加进度
this.progress +=progress;
// 显示当前进度
progressText = String.valueOf(this.progress);
// 重新绘制
invalidate();
}
}
/**
* 减少进度
*/
public void decreaseProgress(int progress) {
if (this.progress > 0) {
// 减少进度
this.progress-=progress;
// 显示当前进度
progressText = String.valueOf(this.progress);
// 重新绘制
invalidate();
}
}
}
2、activity_main
<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:gravity="center">
<com.example.customview.CircleProgressBar
android:id="@+id/customProgressBar"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginBottom="16dp" />
<Button
android:id="@+id/increaseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+" />
<Button
android:id="@+id/decreaseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-" />
</LinearLayout>
3、MainActivity.java
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val customCircleView = findViewById<CircleProgressBar>(R.id.customProgressBar)
val increaseButton = findViewById<Button>(R.id.increaseButton)
val decreaseButton = findViewById<Button>(R.id.decreaseButton)
increaseButton.setOnClickListener { customCircleView.increaseProgress(10) }
decreaseButton.setOnClickListener { customCircleView.decreaseProgress(10) }
}
}