在之前的工作中,有一个需求是判断已用和剩余油量用环形进度条的方式展示的。改方面的数据是通过串口从底层获取过来的,这边我就随便拿个数来填充就好了。当时由于上级的要求就自己写了一个比较简单的出来。好的,那么今天将跟大家分享如何自定义一个环形进度条,也算是对这方面的知识进行一个总结。下面我们开始实现这个功能。那么首先还是先上代码:
package com.example.circularprogressbar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
public class CircleView extends View {
/**
* 定义画笔
*/
private Paint paint = null;
/**
* 当前弧度
*/
private int currArc = 0;
/**
* 进度百分比
*/
private int progressPrecent = 0;
/**
* 环形进度的半径大小
*/
private int progressCircleRadius = 100;
/**
* 用户设置的进度
*/
private int setProgress = 0;
public CircleView(Context context) {
super(context);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public void initPaint() {
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Style.STROKE);// 设置空心
paint.setTextAlign(Align.CENTER);
paint.setTextSize(20);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
// 画圆
drawCircle(canvas);
// 绘制弧线区域
drawArc(canvas);
// 画文字
drawText(canvas);
// 画椭圆,参数一是扫描区域,参数二为paint对象
// drawOval(RectF oval, Paint paint);
}
private void drawArc(Canvas canvas) {
paint.setColor(Color.RED);
RectF oval = new RectF(-progressCircleRadius, -progressCircleRadius, progressCircleRadius, progressCircleRadius);
currArc++;
/**
* 参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、弧度;<br/>
* 参数二是弧度起始角度位置;<br/>
* 参数三扫描角度开始顺时针测量;<br/>
* 参数四是如果设置为true,则包括椭圆中心的弧度,并关闭它,如果设置为false,则是一个弧线;<br/>
* 参数五是Paint对象;
*/
canvas.drawArc(oval, 270, currArc, false, paint);
}
private void drawText(Canvas canvas) {
paint.setStrokeWidth(2);
progressPrecent = (currArc * 100) / 360;
canvas.drawText(String.valueOf(progressPrecent), 0, 0, paint);
}
private void drawCircle(Canvas canvas) {
paint.setColor(Color.BLUE);
paint.setStrokeWidth(20);
// 将画布位置移动到画布宽度的中心(x),高度的中心-环形进度的半径(y)的坐标点
canvas.translate(canvas.getWidth() >> 1, (canvas.getHeight() >> 1) - progressCircleRadius);
/**
* 参数一是中心点的x轴; <br/>
* 参数二是中心点的y轴; <br/>
* 参数三是半径;<br/>
* 参数四是paint对象;<br/>
*/
canvas.drawCircle(0, 0, progressCircleRadius, paint);
}
Handler updateViewHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (progressPrecent < setProgress) {
updateViewHandler.sendEmptyMessageDelayed(0, 20);
invalidate();
}
}
};
/**
* 设置进度值
*
* @param progress
*/
public void setProgress(int progress) {
updateViewHandler.removeMessages(0);
// 弧度回退
currArc = 0;
// 进度回退
progressPrecent = 0;
// 用户设置的进度
this.setProgress = progress;
updateViewHandler.sendEmptyMessage(0);
}
public int getProgress() {
return progressPrecent;
}
@Override
protected void onDetachedFromWindow() {
updateViewHandler.removeMessages(0);
super.onDetachedFromWindow();
}
}
这个环形进度条是一个view,是的,它是画出来的view,那么既然是draw出来,我们这边就写一个CircleView继承于view实现该实现的ondraw()方法。首先在构造函数中初始化一个支画笔,然后在ondraw()中去画我们的环形进度条。那么我们再看看效果图:
下面来谈谈这个代码思路,当然做法是相当的多,这边只是简单聊聊我这边的原理。
该环形进度条由三部分组成,第一部分是内部蓝色的圆圈,第二部分是覆盖在蓝色圆圈上的红色弧线,还有最后的文本写在圆弧内即可。
在ondraw()中我们定义三个方法:
1、draw蓝色圆形(背景图) 2、draw红色弧线 3、draw文本
蓝色环形部分draw出来之后是放在那里不用改变的,改变的是红色弧线和文本内容
首先我们先将canvas移动到view的中心点,然后拿该点作为圆心画蓝色部分,这边的半径就是draw红色弧线的区域大小,否则将不能恰好覆盖在蓝色环形上,其实这边对于不熟悉绘图API的同学来说就是这里取距离比较麻烦,这边我在代码中已经对绘图API的参数进行了说明了。那么最后就是draw文本内容了,draw文本的位置直接设置在圆心上就可以了。再来就是文本内用,这边是将整个圆划分为100的,但是draw红色弧线是以角度360°来算的,那么转换一下就好了 进度百分比 = (当前弧度 * 100) / 360;
好了,就这么点东西!
最后在xml中应用
在activity中