业务图,业务代码
public class RoseChart extends View { //图标尺寸 private int chart_size; private static Context context; //传入参数(各个风向百分比) private List<Float> percentageList; private List<String> nameList; private List<Integer> colorList; //画笔初始化 private Paint paintArc = new Paint();//扇形图 private Paint paintLabel = new Paint();//一层一层圈 private Paint paintCircular = new Paint();//中间圆 // 画笔绘制中间的文字 private Paint paintCenterText = new Paint(); private String mText = "000%"; ; public RoseChart(Context context) { super(context, null); this.context = context; initData(); } private void initData() { percentageList = new ArrayList<>(); percentageList.add(40f); percentageList.add(50f); percentageList.add(60f); percentageList.add(35f); percentageList.add(70f); percentageList.add(80f); percentageList.add(90f); nameList = new ArrayList<>(); nameList.add("N"); nameList.add("NNE"); nameList.add("NE"); nameList.add("ENE"); nameList.add("E"); nameList.add("ESE"); nameList.add("SE"); colorList = new ArrayList<>(); colorList.add(Color.RED); colorList.add(Color.BLUE); colorList.add(Color.YELLOW); colorList.add(Color.GRAY); colorList.add(Color.MAGENTA); colorList.add(Color.LTGRAY); colorList.add(Color.CYAN); colorList.add(Color.GREEN); mText = "45%"; } public RoseChart(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context = context; initData(); } @Override public void onDraw(Canvas canvas) { //画布背景 canvas.drawColor(getResources().getColor(R.color.white)); float cirX = getWidth() / 2; float cirY = getHeight() / 2; //计算绘制区域半径 float radius = (float) (getHeight() * 0.42);//150; paintLabel.setColor(Color.parseColor("#DDDDDD")); paintLabel.setAntiAlias(true); paintArc.setAntiAlias(true); //位置计算类 XChartCalc xcalc = new XChartCalc(); float Percentage = 0.0f; float CurrPer = 0.0f;//绘制 扇形区域 当前起始角度 float CurrPerLabel = 0.0f;//绘制 风向标识 当前起始角度 float NewRaidus = 0.0f; //计算每个扇区的圆心角度数 // Percentage = 360 / arrPerLabel.length; // Percentage = (float) (Math.round(Percentage * 100)) / 100; Percentage = (float) round(360.00 / nameList.size(), 2); //计算起始扇形区域角度(默认顺时针方向 N-->NNE-->NE-->ENE-->E.....填充扇区) CurrPer -= (float) round((Percentage - 4) / 2, 2); CurrPerLabel -= (float) round((Percentage - 4) / 2, 2); //绘制外圈,等分比 paintLabel.setStyle(Paint.Style.STROKE); paintLabel.setStrokeCap(Paint.Cap.BUTT); canvas.drawCircle(cirX, cirY, radius, paintLabel); canvas.drawCircle(cirX, cirY, (float) (radius * 0.875), paintLabel); canvas.drawCircle(cirX, cirY, (float) (radius * 0.75), paintLabel); canvas.drawCircle(cirX, cirY, (float) (radius * 0.625), paintLabel); canvas.drawCircle(cirX, cirY, (float) (radius * 0.5), paintLabel); canvas.drawCircle(cirX, cirY, (float) (radius * 0.375), paintLabel); //绘制三个不同百分比标识 //1,取出最大百分比 Float max = Collections.max(percentageList); //绘制 风向 扇区 for (int i = 0; i < percentageList.size(); i++) { //将百分比转换为新扇区的半径 if (percentageList.get(i) == max) { NewRaidus = radius; } else { NewRaidus = radius * (percentageList.get(i) / max); NewRaidus = (float) (Math.round(NewRaidus * 100)) / 100; } float NewarcLeft = cirX - NewRaidus; float NewarcTop = cirY - NewRaidus; float NewarcRight = cirX + NewRaidus; float NewarcBottom = cirY + NewRaidus; RectF NewarcRF = new RectF(NewarcLeft, NewarcTop, NewarcRight, NewarcBottom); //分配颜色 paintArc.setColor(colorList.get(i)); paintArc.setAlpha(255); //在饼图中显示所占比例 canvas.drawArc(NewarcRF, CurrPer - 90, Percentage, true, paintArc); //下次的起始角度 CurrPer += Percentage; } //绘制外圈风向标识 for (int j = 0; j < nameList.size(); j++) { //计算百分比标签 xcalc.CalcArcEndPointXY(cirX, cirY, radius, (float) (CurrPerLabel + (Percentage - 4) * 0.5)); //标识 paintLabel.setColor(Color.BLACK); paintLabel.setTextSize(getResources().getDimension(R.dimen.RoseChart_direction)); paintLabel.setStrokeWidth((float) 0.8); canvas.drawText(nameList.get(j), xcalc.getPosX(), xcalc.getPosY(), paintLabel); //下次的起始角度 CurrPerLabel += Percentage; } paintLabel.setColor(Color.BLACK); //中心画圆 paintCircular.setColor(Color.WHITE); canvas.drawCircle(cirX, cirY, (float) (radius * 0.25), paintCircular); //绘制中心文字 paintCenterText.setColor(Color.BLACK); paintCenterText.setTextSize(60);
paintCenterText.setTypeface(Typeface.DEFAULT_BOLD);//设置粗体
// 要重新设置宽度为0 paintCenterText.setStrokeWidth(0); // 得到指定文本边界的指定大小 Rect bounds = new Rect(); paintCenterText.getTextBounds(mText, 0, mText.length(), bounds); canvas.drawText(mText, cirX - bounds.width() / 2, cirY + bounds.height() / 2, paintCenterText); } public static class XChartCalc { private static float x; private static float y; private static float r; public static void CalcArcEndPointXY(float cirX, float cirY, float radius, float Percentage) { double a = 2 * Math.PI * (Percentage / 360); if (Percentage >= 0 && Percentage < 130) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance1); } else if (Percentage >= 130 && Percentage < 180) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance2); } else if (Percentage == 180) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3); } else if (Percentage > 180 && Percentage < 240) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance4); } else if (Percentage > 240 && Percentage < 270) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5); } else if (Percentage == 270) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6); } else if (Percentage > 270 && Percentage < 300) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance5); } else if (Percentage >= 300 && Percentage < 330) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance6); } else if (Percentage >= 330 && Percentage < 350) { r = radius + context.getResources().getDimension(R.dimen.RoseChart_distance3); } y = cirY - (float) (r * (Math.cos(a))); x = cirX + (float) (r * (Math.sin(a))); } public static float getPosX() { return x; } public static float getPosY() { return y; } } /** * 返回指定小数位数 * * @param v * @param scale * @return */ public static double round(double v, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b = new BigDecimal(Double.toString(v)); BigDecimal one = new BigDecimal("1"); return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); } public void setColorText(List<String> nameSize,List<Float> percentSize,List<Integer> colorSize,String percentText) { percentageList.clear(); nameList.clear(); colorList .clear(); mText = percentText; invalidate(); } }
<dimen name="RoseChart_persent">10sp</dimen> <dimen name="RoseChart_direction">8sp</dimen> <dimen name="RoseChart_distance1">4dp</dimen> <dimen name="RoseChart_distance2">8dp</dimen> <dimen name="RoseChart_distance3">10dp</dimen> <dimen name="RoseChart_distance4">16dp</dimen> <dimen name="RoseChart_distance5">22dp</dimen> <dimen name="RoseChart_distance6">12dp</dimen>
//直接复制黏贴,运行就行,整合了好几篇博客写的
感谢https://blog.csdn.net/qq_35178316/article/details/61200170 这个写的是玫瑰图(复制黏贴的基本全部的代码)
https://blog.csdn.net/xcl168/article/details/23222417 这个写的是玫瑰图 (复制黏贴的部分样式调整的参考)
https://github.com/NewHuLe/RingProgressView 这个写的是环形进度圈(复制黏贴的中间的文字和中间白圆)