目录
思路来源于Homilier,感谢博主!
效果是这样子的:
思路
从RadarChart类中我们可以看到init()方法中的内容,可以看出来自定义了绘制类。仅从字面我们就可以看出RadarChartRenderer是绘制雷达的,YAxisRendererRadarChart和XAxisRendererRadarChart是绘制x轴/y轴相关内容的,既然这样那我们就清楚了,进RadarChartRenderer看看里面的实现;
从方法名上就可以看出端倪,drawValues(Canvas c) 是咱重点关注的内容。所以在这开造。
实现
直接贴代码,很基础的绘制代码,就不做介绍了。代码过长,没必要的就直接用省略号了,对比下RadarChartRenderer即可
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添加三个方法
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);
}
........
}
自己项目中应用:
@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")
});
}
来源:oschina
链接:https://my.oschina.net/u/4405012/blog/4333735