环形进度条
如上图所示,之所以想到写这个,因为项目中有这样的需求,所以自己就去琢磨琢磨该怎么去实现这个需求。
实现思路:
① 画个圆弧
② 圆弧上画个圆
③ 画进度条
④ 在圆弧的中心绘制进度值
好了,思路已经有了,我们现在一个一个来实现。
画个圆弧
canvas.drawArc(rectF, 45, 270, false, mRingPaint);
这样就画了一个我们需要的圆弧。
圆弧上画个圆
画圆就需要圆心和半径。半径比较好得到。这里就半径用到了点数学上的知识。
float radius = (float) ((width - mArcDis - mArcDis) / 2);
float pointX = (float) (mCircleX + radius * Math.cos(mSwipeAngle * 3.14 / 180));
float pointY = (float) (mCircleY + radius * Math.sin(mSwipeAngle * 3.14 / 180));
画进度条
这里的进度条,就是重新绘制一个重合的圆弧
canvas.drawArc(rectF, 45, mSwipeAngle-45, false, mSwipePaint);
在圆弧的中心绘制进度值
float v = mTextPaint.measureText(String.valueOf((int) Math.floor((float) (mSwipeAngle - 45) / 270 * 100)));
canvas.drawText(String.valueOf((int)Math.floor((float)(mSwipeAngle-45)/270*100)),mCircleX-(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mTextPaint);
canvas.drawText("%",mCircleX+(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mPercentPaint);
下面给出全部代码以供参考:
public class CircleRingView extends View {
private int mArcDis;
private Paint mRingPaint;
private Paint mPointPaint;
private int mPointAngle;
private float mCircleX;
private float mCircleY;
private int mSwipeAngle=45;
private Handler mHandler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mSwipeAngle == mPointAngle) {
mHandler.removeMessages(0);
}else {
++mSwipeAngle;
postInvalidate();
}
}
};
private Paint mSwipePaint;
private Paint mTextPaint;
private Paint mPercentPaint;
public CircleRingView(Context context) {
this(context, null);
}
public CircleRingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleRingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initParams(context);
}
private void initParams(Context context) {
//圆弧Paint
mRingPaint = new Paint();
mRingPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 3));
mRingPaint.setAntiAlias(true);
mRingPaint.setStyle(Paint.Style.STROKE);
mRingPaint.setColor(ContextCompat.getColor(context, R.color.white));
//圆弧上的圆的Paint
mPointPaint = new Paint();
mPointPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
mPointPaint.setAntiAlias(true);
mPointPaint.setStyle(Paint.Style.FILL);
mPointPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
//进度条Paint
mSwipePaint = new Paint();
mSwipePaint.setStrokeWidth(Px2DpUtil.dp2px(context,3));
mSwipePaint.setAntiAlias(true);
mSwipePaint.setStyle(Paint.Style.STROKE);
mSwipePaint.setColor(ContextCompat.getColor(context, R.color.bg_gradient_start));
//进度值Paint
mTextPaint = new Paint();
mTextPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
mTextPaint.setTextSize(Px2DpUtil.sp2px(context,40));
//百分号Paint
mPercentPaint = new Paint();
mPercentPaint.setStrokeWidth(Px2DpUtil.dp2px(context, 1));
mPercentPaint.setAntiAlias(true);
mPercentPaint.setStyle(Paint.Style.FILL);
mPercentPaint.setColor(ContextCompat.getColor(context, R.color.c_3ec88e));
mPercentPaint.setTextSize(Px2DpUtil.sp2px(context,25));
//Rectf所需要
mArcDis = Px2DpUtil.dp2px(context, 20);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
RectF rectF = new RectF();
rectF.left = mArcDis;
rectF.top = mArcDis;
rectF.right = width - mArcDis;
rectF.bottom = height - mArcDis;
canvas.rotate(90, width / 2, height / 2);
//正常圆弧
canvas.drawArc(rectF, 45, 270, false, mRingPaint);
if (mSwipeAngle>=0&&mSwipeAngle <= 45) {
mSwipeAngle = 45;
mPointAngle=45;
} else if (mSwipeAngle > 315 & mSwipeAngle <= 360) {
mSwipeAngle = 315;
mPointAngle = 315;
}
mCircleX = width / 2;
mCircleY = height / 2;
if(mSwipeAngle<=mPointAngle) {
float radius = (float) ((width - mArcDis - mArcDis) / 2);
float pointX = (float) (mCircleX + radius * Math.cos(mSwipeAngle * 3.14 / 180));
float pointY = (float) (mCircleY + radius * Math.sin(mSwipeAngle * 3.14 / 180));
//进度圆弧,模仿进度条
canvas.drawArc(rectF, 45, mSwipeAngle-45, false, mSwipePaint);
//圆弧上的圆
canvas.drawCircle(pointX, pointY, Px2DpUtil.dp2px(getContext(), 10), mPointPaint);
canvas.rotate(-90, width / 2, height / 2);
//测量文本宽度
float v = mTextPaint.measureText(String.valueOf((int) Math.floor((float) (mSwipeAngle - 45) / 270 * 100)));
//绘制文本
canvas.drawText(String.valueOf((int)Math.floor((float)(mSwipeAngle-45)/270*100)),mCircleX-(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mTextPaint);
//绘制百分号
canvas.drawText("%",mCircleX+(int)v/2,mCircleY+Px2DpUtil.dp2px(getContext(),10),mPercentPaint);
mHandler.sendEmptyMessageDelayed(0, 10);
}
}
//需要画的进度值
public void setProgressValue(int value){
int swipeAngle = (int) (((float)value / 100) * 360);
mPointAngle= swipeAngle;
mHandler.sendEmptyMessageDelayed(0, 10);
}
//停止绘制View
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mHandler.removeMessages(0);
mHandler=null;
}
}
到这里,整个控件的实现方法就都写完了。