Android-MPAndroidChart:RadarChart(雷达蜘蛛图)绘制圆点

无人久伴 提交于 2020-08-20 07:51:08

目录

思路

实现


思路来源于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")
        });
  
    }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!