目录
思路
实现
思路来源于Homilier,感谢博主!
效果是这样子的:
思路
从RadarChart类中我们可以看到init()方法中的内容,可以看出来自定义了绘制类。仅从字面我们就可以看出RadarChartRenderer是绘制雷达的,YAxisRendererRadarChart和XAxisRendererRadarChart是绘制x轴/y轴相关内容的,既然这样那我们就清楚了,进RadarChartRenderer看看里面的实现;
从方法名上就可以看出端倪,drawValues(Canvas c) 是咱重点关注的内容。所以在这开造。
实现
直接贴代码,很基础的绘制代码,就不做介绍了。代码过长,没必要的就直接用省略号了,对比下RadarChartRenderer即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | public class RadarChartRenderer extends LineRadarRenderer { protected RadarChart mChart; /** * paint for drawing the web */ protected Paint mWebPaint; protected Paint mHighlightCirclePaint; public RadarChartRenderer(RadarChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.STROKE); mHighlightPaint.setStrokeWidth(2f); mHighlightPaint.setColor(Color.rgb(255, 187, 115)); mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mWebPaint.setStyle(Paint.Style.STROKE); mHighlightCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mValueCirclePaint = new Paint(); } protected Path mDrawDataSetSurfacePathBuffer = new Path(); ......... /** * 绘制RadarDataSet * * @param c * @param dataSet * @param mostEntries 条目最多的数据集的条目计数 */ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); float sliceangle = mChart.getSliceAngle(); // 计算将值转换为像素所需的因子 float factor = mChart.getFactor(); MPPointF center = mChart.getCenterOffsets(); MPPointF pOut = MPPointF.getInstance(0, 0); Path surface = mDrawDataSetSurfacePathBuffer; surface.reset(); boolean hasMovedToPoint = false; for (int j = 0; j < dataSet.getEntryCount(); j++) { mRenderPaint.setColor(dataSet.getColor(j)); RadarEntry e = dataSet.getEntryForIndex(j); Utils.getPosition(center, (e.getY() - mChart.getYChartMin()) * factor * phaseY, sliceangle * j * phaseX + mChart.getRotationAngle(), pOut); if (Float.isNaN(pOut.x)) { continue; } if (!hasMovedToPoint) { surface.moveTo(pOut.x, pOut.y); hasMovedToPoint = true; } else { surface.lineTo(pOut.x, pOut.y); } } if (dataSet.getEntryCount() > mostEntries) { // if this is not the largest set, draw a line to the center before closing surface.lineTo(center.x, center.y); } surface.close(); if (dataSet.isDrawFilledEnabled()) { final Drawable drawable = dataSet.getFillDrawable(); if (drawable != null) { drawFilledPath(c, surface, drawable); } else { drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha()); } } mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); mRenderPaint.setStyle(Paint.Style.STROKE); // 画线(仅当禁用填充或alpha小于255时) if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) { c.drawPath(surface, mRenderPaint); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); } private Paint mValueCirclePaint; private float mValueCircleRadius = Utils.convertDpToPixel(5f); private int[] mValueCircleColors; private boolean mDrawValueCircle = false; private float mValueCircleRadiusUp = Utils.convertDpToPixel(3f); private int[] mValueCircleColorsUp; private boolean mDrawValueCircleUp = false; /** * 绘制数值-也就是和数值相关的位置 * * @param c */ @Override public void drawValues(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); float sliceangle = mChart.getSliceAngle(); // 计算将值转换为像素所需的因子 float factor = mChart.getFactor(); MPPointF center = mChart.getCenterOffsets(); MPPointF pOut = MPPointF.getInstance(0, 0); MPPointF pIcon = MPPointF.getInstance(0, 0); float yoffset = Utils.convertDpToPixel(5f); for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { IRadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); if (!shouldDrawValues(dataSet)) { continue; } // 应用数据集定义的文本样式 applyValueTextStyle(dataSet); ValueFormatter formatter = dataSet.getValueFormatter(); MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); for (int j = 0; j < dataSet.getEntryCount(); j++) { RadarEntry entry = dataSet.getEntryForIndex(j); Utils.getPosition(center, (entry.getY() - mChart.getYChartMin()) * factor * phaseY, sliceangle * j * phaseX + mChart.getRotationAngle(), pOut); if (dataSet.isDrawValuesEnabled()) { drawValue(c, formatter.getRadarLabel(entry), pOut.x, pOut.y - yoffset, dataSet.getValueTextColor(j)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { Drawable icon = entry.getIcon(); Utils.getPosition(center, (entry.getY()) * factor * phaseY + iconsOffset.y, sliceangle * j * phaseX + mChart.getRotationAngle(), pIcon); //无检查SuspiciousNameCombination pIcon.y += iconsOffset.x; Utils.drawImage(c, icon, (int) pIcon.x, (int) pIcon.y, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); } if (mDrawValueCircle) { mValueCirclePaint.setColor(mValueCircleColors == null || mValueCircleColors.length == 0 ? Color.BLACK : this.mValueCircleColors[i % mValueCircleColors.length]); c.drawCircle(pOut.x, pOut.y, mValueCircleRadius, mValueCirclePaint); } if (mDrawValueCircleUp) { mValueCirclePaint.setColor(mValueCircleColorsUp == null || mValueCircleColorsUp.length == 0 ? Color.BLACK : this.mValueCircleColorsUp[i % mValueCircleColorsUp.length]); c.drawCircle(pOut.x, pOut.y, mValueCircleRadiusUp, mValueCirclePaint); } // c.drawCircle(center.x, center.y, 8, mWebPaint); } MPPointF.recycleInstance(iconsOffset); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); MPPointF.recycleInstance(pIcon); } /** * 数值圆点颜色 * * @param colors 颜色 */ public void setValueCircleColor(int[] colors, int[] colorsUp) { this.mValueCircleColors = colors; this.mValueCircleColorsUp = colorsUp; } /** * 数值圆点半径 * * @param radius 半径 */ public void setValueCircleRadius(float radius, float radiusUp) { this.mValueCircleRadius = Utils.convertDpToPixel(radius); this.mValueCircleRadiusUp = Utils.convertDpToPixel(radiusUp); } /** * 是否绘制数值圆点 * * @param draw */ public void setDrawValueCircle(boolean draw, boolean drawUp) { this.mDrawValueCircleUp = drawUp; this.mDrawValueCircle = draw; } ......... } |
RadarChart添加三个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class RadarChart extends PieRadarChartBase<RadarData> { ........ /** * 顶角圆点颜色 * @param colors 颜色 */ public void setValueCircleColor(int[] colors,int[] colorsUp){ ((RadarChartRenderer) this.mRenderer).setValueCircleColor(colors,colorsUp); } /** * 顶角圆点半径 * @param radius 半径 */ public void setValueCircleRadius(float radius,float radiusUp){ ((RadarChartRenderer) this.mRenderer).setValueCircleRadius(radius,radiusUp); } /** * 是否绘制顶角圆点 * @param draw */ public void setDrawValueCircle(boolean draw,boolean drawUp){ ((RadarChartRenderer) this.mRenderer).setDrawValueCircle(draw,drawUp); } ........ } |
自己项目中应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_radarchart); RadarChart chart = findViewById(R.id.chart1); chart.setWebLineWidth(1f); chart.setWebColor(Color.LTGRAY); chart.setWebLineWidthInner(1f); chart.setWebColorInner(Color.LTGRAY); chart.setWebAlpha(100); // 创建一个自定义MarkerView(扩展MarkerView)并指定布局用它 MarkerView mv = new RadarMarkerView(this, R.layout.radar_markerview); //重点在这 //设置数据圆点 第一个true表示绘制下层圆 第二个true绘制上层圆 形成圆环形式的圆 chart.setDrawValueCircle(true, true); //设置半径 第一个参数大于第二个参数 才会有圆环的那种样子 chart.setValueCircleRadius(6, 4); //可以设置多个颜色,第一个数组是下层圆 第二个数组是下层圆 chart.setValueCircleColor(new int[]{ Color.parseColor("#36a9ce"), Color.parseColor("#33ff66"), }, new int[]{ Color.parseColor("#ffffff"), Color.parseColor("#000000") }); } |