好久不寫博客了 最近項目中用到一個環形比例圖,分享一下
先上效果圖
其實是挺簡單的,調用幾次drawArc而已,簡單封裝了一下
有點細節的是,當要畫的圓弧數量大於1即不是某一比例值爲100%,以最上方爲起始點逆時針開始畫,從最小值向最大值畫,因爲看到圓弧的端口是一個壓着一個的,所以畫完後要再畫起始圓弧的一半,不然最大一段圓弧(也就是最後畫的圓弧)的兩個圓角端口都是可見的。
使用時非常的簡單:
<com.sign.EasyRingView
android:id="@+id/erv_scale"
android:layout_width="300dp"
android:layout_height="300dp" />
List<String[]> list = new ArrayList<>();
list.add(new String[]{"0.2", "#9B9B9B"});//gray
list.add(new String[]{"0.3", "#29C7BA"});//theme
list.add(new String[]{"0.4", "#518ef8"});//blue
list.add(new String[]{"0.05", "#ff9500"});//yellow
list.add(new String[]{"0.05", "#F67D88"});//tip
ervScale.setAngleAndColorList(list);
public class EasyRingView extends View {
private Context mContext;
private Paint mPaint;
private int mDefaultColor;
private float mRingWidth;
private List<AngleAndColorBean> mAngleAndColorList;
public EasyRingView(Context context) {
this(context, null);
}
public EasyRingView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public EasyRingView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}
private void init() {
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mRingWidth = Utils.dp2px(mContext, 20);
mPaint.setStrokeWidth(mRingWidth);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mDefaultColor = ContextCompat.getColor(mContext, R.color.gray);
}
public void setRingWidth(float width) {
mRingWidth = width;
if (mPaint != null) {
mPaint.setStrokeWidth(width);
invalidate();
}
}
public void setAngleAndColorList(@NonNull List<String[]> scaleAndColorList) {
if (mAngleAndColorList == null) {
mAngleAndColorList = new ArrayList<>();
} else {
mAngleAndColorList.clear();
}
if (scaleAndColorList.size() == 0) {
mAngleAndColorList.add(new AngleAndColorBean(360, mDefaultColor));
} else {
float angleSum = 0;
for (String[] scaleAndColor : scaleAndColorList) {
float angle;
try {
angle = Float.parseFloat(scaleAndColor[0]) * 360;
} catch (NumberFormatException e) {
angle = 0;
}
int color;
try {
color = Color.parseColor(scaleAndColor[1]);
} catch (Exception e) {
color = mDefaultColor;
}
if (angle > 0) {
mAngleAndColorList.add(new AngleAndColorBean(angle, color));
angleSum += angle;
}
}
if (angleSum < 360 && mAngleAndColorList.size() > 0) {
//avoid sum not equal 360
Collections.sort(mAngleAndColorList, (o1, o2) -> {
if (o1.getAngle() > o2.getAngle()) {
return 1;
} else if (o1.getAngle() < o2.getAngle()) {
return -1;
}
return 0;
});
mAngleAndColorList.get(0).setAngle(mAngleAndColorList.get(0).getAngle() + (360 - angleSum));
}
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mAngleAndColorList == null || mAngleAndColorList.size() == 0) {
return;
}
float left = mRingWidth / 2;
float top = mRingWidth / 2;
float right = getMeasuredWidth() - mRingWidth / 2;
float bottom = getMeasuredHeight() - mRingWidth / 2;
if (mAngleAndColorList.size() > 1) {
float startAngle = -90;
for (int i = mAngleAndColorList.size() - 1; i >= 0; i--) {
AngleAndColorBean angleAndColorBean = mAngleAndColorList.get(i);
mPaint.setColor(angleAndColorBean.getColor());
canvas.drawArc(left, top, right, bottom, startAngle - angleAndColorBean.getAngle(), angleAndColorBean.getAngle(), false, mPaint);
startAngle -= angleAndColorBean.getAngle();
}
//avoid the last scale has two corner
AngleAndColorBean lastBean = mAngleAndColorList.get(mAngleAndColorList.size() - 1);
mPaint.setColor(lastBean.getColor());
canvas.drawArc(left, top, right, bottom, -90 - lastBean.getAngle() / 2, lastBean.getAngle() / 2, false, mPaint);
} else {
mPaint.setColor(mAngleAndColorList.get(0).getColor());
canvas.drawArc(left, top, right, bottom, 0, 360, false, mPaint);
}
}
private class AngleAndColorBean {
//所佔角度
private float angle;
//色值
private int color;
AngleAndColorBean(float angle, int color) {
this.angle = angle;
this.color = color;
}
float getAngle() {
return angle;
}
void setAngle(float angle) {
this.angle = angle;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
}
}