美文网首页我爱编程
MPAndroidChart饼图(PieChart)Value值

MPAndroidChart饼图(PieChart)Value值

作者: 茶And狗狗 | 来源:发表于2018-04-17 10:18 被阅读0次

    说明:下文中的bug已经在MPAndroidChart饼图(PieChart)Value值重叠的解决方法(二)中完美解决了,可以去看看。

    先看下前后对比的效果图

    修改前.jpg 修改后.jpg

    背景

    项目做完出来的时候,我就发现了这个问题,奈何在网上没找解决办法,而我又是个Android渣渣,本来准备蒙混过关的,可是测试一定要我改,没办法只能看看MPAndroidChart里的可能涉及到的源码,看下能不能改好。所以,如果有不对和优化的地方,希望大家能指出,相互进步。

    已知bug

    (已经在MPAndroidChart饼图(PieChart)Value值重叠的解决方法(二)中解决了)
    PieChart不能设置为可以转动,即pieChart.setRotationEnabled(false);要设置成false,如果转动,会在转动的时候导致值的位置错乱,知道怎么解决的同学请指点,有空我也看看能不能解决。

    思路

    网上有一个解决方案是,把占比较小部分的值不显示出来,但是博主也说,还是会有重叠的可能,不过大家可以看下地址
    我的思路是,每次都记住上一个值Y方向位置,和这次对比,如果间距小于了值字体的高度,则改变本次画值的位置

    实现步骤

    • 通过观察原生态的PieChart,发现饼图绘制过程,其实画值的过程是由mRenderer实现的,如下:
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
        
                if (mData == null)
                    return;
        
                mRenderer.drawData(canvas);
        
                if (valuesToHighlight())
                    mRenderer.drawHighlighted(canvas, mIndicesToHighlight);
        
                mRenderer.drawExtras(canvas);
        
                mRenderer.drawValues(canvas);
        
                mLegendRenderer.renderLegend(canvas);
        
                drawDescription(canvas);
        
                drawMarkers(canvas);
            }
    

    所以,我们只需要修改mRenderer中画图的实现步骤就好了,那我们就需要把这个mRenderer替换成我们自己定义的PieChartRenderer,而mRenderer又是在下面这个方法中初始化的:

        @Override
        protected void init() {
            super.init();
    
            mRenderer = new PieChartRenderer(this, mAnimator, mViewPortHandler);
            mXAxis = null;
    
            mHighlighter = new PieHighlighter(this);
        }
    

    因为我没找到可以直接设置mRenderer的方法,所以我们需要自己创建一个PieChart的子类,重写init()方法,让mRenderer变成我们自己的PieChartRenderer。

    • 先创建我们自己的PieChartRenderer吧,创建一个类继承PieChartRenderer,有一个被注释的drawValues(Canvas c)方法是饼图左右两边上边对其,效果可以自己打开试下(因为我感觉遍历了太多次,所以就没有使用),其他的代码中关键部分都有说明,就不细说了,代码如下:
    public class MyPieChartRenderer extends PieChartRenderer {
        private static final String TAG = "MyPieChartRenderer";
    
        public MyPieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
            super(chart, animator, viewPortHandler);
        }
    
        String text = "2.0%";
    
        /**
         * 这个方法,左边是从下往上画,右边是从上往下画
         * @param c
         */
        @Override
        public void drawValues(Canvas c) {
    
            Rect rect = new Rect();
            getPaintEntryLabels().getTextBounds(text, 0, text.length(), rect);
            int textHeight = rect.height();//文本的高度
    
            MPPointF center = mChart.getCenterCircleBox();
    
            // get whole the radius
            float radius = mChart.getRadius();
            float rotationAngle = mChart.getRotationAngle();
            float[] drawAngles = mChart.getDrawAngles();
            float[] absoluteAngles = mChart.getAbsoluteAngles();
    
            float phaseX = mAnimator.getPhaseX();
            float phaseY = mAnimator.getPhaseY();
    
            final float holeRadiusPercent = mChart.getHoleRadius() / 100.f;
            float labelRadiusOffset = radius / 10f * 3.6f;
    
            if (mChart.isDrawHoleEnabled()) {
                labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f;
            }
    
            final float labelRadius = radius - labelRadiusOffset;
    
            PieData data = mChart.getData();
            List<IPieDataSet> dataSets = data.getDataSets();
    
            float yValueSum = data.getYValueSum();
    
            boolean drawEntryLabels = mChart.isDrawEntryLabelsEnabled();
    
            float angle;
            int xIndex = 0;
    
            c.save();
    
            float offset = Utils.convertDpToPixel(5.f);
    
            for (int i = 0; i < dataSets.size(); i++) {
    
                IPieDataSet dataSet = dataSets.get(i);
    
                final boolean drawValues = dataSet.isDrawValuesEnabled();
    
                if (!drawValues && !drawEntryLabels)
                    continue;
    
                final PieDataSet.ValuePosition xValuePosition = dataSet.getXValuePosition();
                final PieDataSet.ValuePosition yValuePosition = dataSet.getYValuePosition();
    
                // apply the text-styling defined by the DataSet
                applyValueTextStyle(dataSet);
    
                float lineHeight = Utils.calcTextHeight(mValuePaint, "Q")
                        + Utils.convertDpToPixel(4f);
    
                IValueFormatter formatter = dataSet.getValueFormatter();
    
                int entryCount = dataSet.getEntryCount();
    
                mValueLinePaint.setColor(dataSet.getValueLineColor());
                mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth()));
    
                final float sliceSpace = getSliceSpace(dataSet);
    
                MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
                iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
                iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
    
                float lastPositionOfLeft = 0;
                float lastPositionOfRight = 0;
    
                for (int j = 0; j < entryCount; j++) {
    
                    PieEntry entry = dataSet.getEntryForIndex(j);
    
                    if (xIndex == 0)
                        angle = 0.f;
                    else
                        angle = absoluteAngles[xIndex - 1] * phaseX;
    
                    final float sliceAngle = drawAngles[xIndex];
                    final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius);
    
                    // offset needed to center the drawn text in the slice
                    final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f;
    
                    angle = angle + angleOffset;
    
                    final float transformedAngle = rotationAngle + angle * phaseY;
    
                    float value = mChart.isUsePercentValuesEnabled() ? entry.getY()
                            / yValueSum * 100f : entry.getY();
    
                    final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD);
                    final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD);
    
                    final boolean drawXOutside = drawEntryLabels &&
                            xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
                    final boolean drawYOutside = drawValues &&
                            yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
                    final boolean drawXInside = drawEntryLabels &&
                            xValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
                    final boolean drawYInside = drawValues &&
                            yValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
    
                    if (drawXOutside || drawYOutside) {
    
                        final float valueLineLength1 = dataSet.getValueLinePart1Length();
                        final float valueLineLength2 = dataSet.getValueLinePart2Length();
                        final float valueLinePart1OffsetPercentage = dataSet.getValueLinePart1OffsetPercentage() / 100.f;
    
                        float pt2x, pt2y;
                        float labelPtx, labelPty;
    
                        float line1Radius;
    
                        if (mChart.isDrawHoleEnabled())
                            line1Radius = (radius - (radius * holeRadiusPercent))
                                    * valueLinePart1OffsetPercentage
                                    + (radius * holeRadiusPercent);
                        else
                            line1Radius = radius * valueLinePart1OffsetPercentage;
    
                        final float polyline2Width = dataSet.isValueLineVariableLength()
                                ? labelRadius * valueLineLength2 * (float) Math.abs(Math.sin(
                                transformedAngle * Utils.FDEG2RAD))
                                : labelRadius * valueLineLength2;
    
                        final float pt0x = line1Radius * sliceXBase + center.x;
                        final float pt0y = line1Radius * sliceYBase + center.y;
    
                        final float pt1x = labelRadius * (1 + valueLineLength1) * sliceXBase + center.x;
                        final float pt1y = labelRadius * (1 + valueLineLength1) * sliceYBase + center.y;
    
                        //左右算法不一样,左边是从下往上排的,即你可以理解为饼图是顺时针方向,从零点排到12点的360度圆形,建议先看else里的,即右边的,方便理解
                        if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) {//左边部分
    //                        pt2x = pt1x - polyline2Width;
                            pt2x = center.x - radius - 5;
                            if (lastPositionOfLeft == 0) {//第一个不用管
                                pt2y = pt1y;
                            } else {
                                if (lastPositionOfLeft - pt1y < textHeight) {//如果上一个labley的位置减去计算出的pt1y的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
                                    pt2y = pt1y - (textHeight - (lastPositionOfLeft - pt1y));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置12,则间距只有lastPositionOfRight-pt1y=2,还需要减去少的textHeight-(lastPositionOfRight-pt1y)=3才行
                                } else {
                                    pt2y = pt1y;
                                }
                            }
                            lastPositionOfLeft = pt2y;//记录上一个lableY方向的位置
    
                            mValuePaint.setTextAlign(Paint.Align.RIGHT);
    
                            if (drawXOutside)
                                getPaintEntryLabels().setTextAlign(Paint.Align.RIGHT);
    
                            labelPtx = pt2x - offset;
                            labelPty = pt2y;
                        } else {//右边部分
    //                        pt2x = pt1x + polyline2Width;
                            pt2x = center.x + radius + 5;
                            if (lastPositionOfRight == 0) {//第一个不用管
                                pt2y = pt1y;
                            } else {
                                if (pt1y - lastPositionOfRight < textHeight) {//如果计算出的pt1y的位置减去上一个labley的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
                                    pt2y = pt1y + (textHeight - (pt1y - lastPositionOfRight));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置8,则间距只有pt1y-lastPositionOfRight=2,还需要加上少的textHeight-(pt1y-lastPositionOfRight)=3才行
                                } else {
                                    pt2y = pt1y;
                                }
                            }
                            lastPositionOfRight = pt2y;//记录上一个lableY方向的位置
                            mValuePaint.setTextAlign(Paint.Align.LEFT);
    
                            if (drawXOutside)
                                getPaintEntryLabels().setTextAlign(Paint.Align.LEFT);
    
                            labelPtx = pt2x + offset;
                            labelPty = pt2y;
                        }
    
                        if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) {
                            c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint);
                            c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint);
                        }
    
                        // draw everything, depending on settings
                        if (drawXOutside && drawYOutside) {
    
                            drawValue(c,
                                    formatter,
                                    value,
                                    entry,
                                    0,
                                    labelPtx,
                                    labelPty,
                                    dataSet.getValueTextColor(j));
    
                            if (j < data.getEntryCount() && entry.getLabel() != null) {
                                drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight);
                            }
    
                        } else if (drawXOutside) {
                            if (j < data.getEntryCount() && entry.getLabel() != null) {
                                drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f);
                            }
                        } else if (drawYOutside) {
    
                            drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet
                                    .getValueTextColor(j));
                        }
                    }
    
                    if (drawXInside || drawYInside) {
                        // calculate the text position
                        float x = labelRadius * sliceXBase + center.x;
                        float y = labelRadius * sliceYBase + center.y;
    
                        mValuePaint.setTextAlign(Paint.Align.CENTER);
    
                        // draw everything, depending on settings
                        if (drawXInside && drawYInside) {
    
                            drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j));
    
                            if (j < data.getEntryCount() && entry.getLabel() != null) {
                                drawEntryLabel(c, entry.getLabel(), x, y + lineHeight);
                            }
    
                        } else if (drawXInside) {
                            if (j < data.getEntryCount() && entry.getLabel() != null) {
                                drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f);
                            }
                        } else if (drawYInside) {
    
                            drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j));
                        }
                    }
    
                    if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
    
                        Drawable icon = entry.getIcon();
    
                        float x = (labelRadius + iconsOffset.y) * sliceXBase + center.x;
                        float y = (labelRadius + iconsOffset.y) * sliceYBase + center.y;
                        y += iconsOffset.x;
    
                        Utils.drawImage(
                                c,
                                icon,
                                (int) x,
                                (int) y,
                                icon.getIntrinsicWidth(),
                                icon.getIntrinsicHeight());
                    }
    
                    xIndex++;
                }
    
                MPPointF.recycleInstance(iconsOffset);
            }
            MPPointF.recycleInstance(center);
            c.restore();
        }
    
        /**
         * 这个方法,是两侧都上往下排列,保证上面整齐
         */
    //    @Override
    //    public void drawValues(Canvas c) {
    //
    //
    //        Rect rect = new Rect();
    //        getPaintEntryLabels().getTextBounds(text, 0, text.length(), rect);
    //        int textHeight = rect.height();//文本的高度
    //
    //        MPPointF center = mChart.getCenterCircleBox();
    //
    //        // get whole the radius
    //        float radius = mChart.getRadius();
    //        float rotationAngle = mChart.getRotationAngle();
    //        float[] drawAngles = mChart.getDrawAngles();
    //        float[] absoluteAngles = mChart.getAbsoluteAngles();
    //
    //        float phaseX = mAnimator.getPhaseX();
    //        float phaseY = mAnimator.getPhaseY();
    //
    //        final float holeRadiusPercent = mChart.getHoleRadius() / 100.f;
    //        float labelRadiusOffset = radius / 10f * 3.6f;
    //
    //        if (mChart.isDrawHoleEnabled()) {
    //            labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f;
    //        }
    //
    //        final float labelRadius = radius - labelRadiusOffset;
    //
    //        PieData data = mChart.getData();
    //        List<IPieDataSet> dataSets = data.getDataSets();
    //
    //        float yValueSum = data.getYValueSum();
    //
    //        boolean drawEntryLabels = mChart.isDrawEntryLabelsEnabled();
    //
    //        float angle;
    //        int xIndex = 0;
    //
    //        c.save();
    //
    //        float offset = Utils.convertDpToPixel(5.f);
    //
    //        for (int i = 0; i < dataSets.size(); i++) {
    //
    //            IPieDataSet dataSet = dataSets.get(i);
    //
    //            final boolean drawValues = dataSet.isDrawValuesEnabled();
    //
    //            if (!drawValues && !drawEntryLabels)
    //                continue;
    //
    //            final PieDataSet.ValuePosition xValuePosition = dataSet.getXValuePosition();
    //            final PieDataSet.ValuePosition yValuePosition = dataSet.getYValuePosition();
    //
    //            // apply the text-styling defined by the DataSet
    //            applyValueTextStyle(dataSet);
    //
    //            float lineHeight = Utils.calcTextHeight(mValuePaint, "Q")
    //                    + Utils.convertDpToPixel(4f);
    //
    //            IValueFormatter formatter = dataSet.getValueFormatter();
    //
    //            int entryCount = dataSet.getEntryCount();
    //
    //            mValueLinePaint.setColor(dataSet.getValueLineColor());
    //            mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth()));
    //
    //            final float sliceSpace = getSliceSpace(dataSet);
    //
    //            MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
    //            iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
    //            iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
    //
    //            float lastPositionOfLeft = 0;
    //            float lastPositionOfRight = 0;
    //
    //            //画右边
    //            for (int j = 0; j < entryCount; j++) {
    //
    //                PieEntry entry = dataSet.getEntryForIndex(j);
    //
    //                if (xIndex == 0)
    //                    angle = 0.f;
    //                else
    //                    angle = absoluteAngles[xIndex - 1] * phaseX;
    //
    //                final float sliceAngle = drawAngles[xIndex];
    //                final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius);
    //
    //                // offset needed to center the drawn text in the slice
    //                final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f;
    //
    //                angle = angle + angleOffset;
    //
    //                final float transformedAngle = rotationAngle + angle * phaseY;
    //
    //                float value = mChart.isUsePercentValuesEnabled() ? entry.getY()
    //                        / yValueSum * 100f : entry.getY();
    //
    //                final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD);
    //                final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD);
    //
    //                final boolean drawXOutside = drawEntryLabels &&
    //                        xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
    //                final boolean drawYOutside = drawValues &&
    //                        yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
    //                final boolean drawXInside = drawEntryLabels &&
    //                        xValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
    //                final boolean drawYInside = drawValues &&
    //                        yValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
    //
    //                if (drawXOutside || drawYOutside) {
    //
    //                    final float valueLineLength1 = dataSet.getValueLinePart1Length();
    //                    final float valueLineLength2 = dataSet.getValueLinePart2Length();
    //                    final float valueLinePart1OffsetPercentage = dataSet.getValueLinePart1OffsetPercentage() / 100.f;
    //
    //                    float pt2x, pt2y;
    //                    float labelPtx, labelPty;
    //
    //                    float line1Radius;
    //
    //                    if (mChart.isDrawHoleEnabled())
    //                        line1Radius = (radius - (radius * holeRadiusPercent))
    //                                * valueLinePart1OffsetPercentage
    //                                + (radius * holeRadiusPercent);
    //                    else
    //                        line1Radius = radius * valueLinePart1OffsetPercentage;
    //
    //                    final float polyline2Width = dataSet.isValueLineVariableLength()
    //                            ? labelRadius * valueLineLength2 * (float) Math.abs(Math.sin(
    //                            transformedAngle * Utils.FDEG2RAD))
    //                            : labelRadius * valueLineLength2;
    //
    //                    final float pt0x = line1Radius * sliceXBase + center.x;
    //                    final float pt0y = line1Radius * sliceYBase + center.y;
    //
    //                    final float pt1x = labelRadius * (1 + valueLineLength1) * sliceXBase + center.x;
    //                    final float pt1y = labelRadius * (1 + valueLineLength1) * sliceYBase + center.y;
    //
    //                    //左右算法不一样,左边是从下往上排的,即你可以理解为饼图是顺时针方向,从零点排到12点的360度圆形,建议先看else里的,即右边的,方便理解
    //                    if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) {//左边部分
    ////                        pt2x = center.x - radius - 5;
    ////                        if (lastPositionOfLeft == 0) {//第一个不用管
    ////                            pt2y = pt1y;
    ////                        } else {
    ////                            if (lastPositionOfLeft - pt1y < textHeight) {//如果上一个labley的位置减去计算出的pt1y的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
    ////                                pt2y = pt1y - (textHeight - (lastPositionOfLeft - pt1y));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置12,则间距只有lastPositionOfRight-pt1y=2,还需要减去少的textHeight-(lastPositionOfRight-pt1y)=3才行
    ////                            } else {
    ////                                pt2y = pt1y;
    ////                            }
    ////                        }
    ////                        lastPositionOfLeft = pt2y;//记录上一个lableY方向的位置
    ////
    ////                        mValuePaint.setTextAlign(Paint.Align.RIGHT);
    ////
    ////                        if (drawXOutside)
    ////                            getPaintEntryLabels().setTextAlign(Paint.Align.RIGHT);
    ////
    ////                        labelPtx = pt2x - offset;
    ////                        labelPty = pt2y;
    //                        break;
    //                    } else {//右边部分
    ////                        pt2x = pt1x + polyline2Width;
    //                        pt2x = center.x + radius + 5;
    //                        if (lastPositionOfRight == 0) {//第一个不用管
    //                            pt2y = pt1y;
    //                        } else {
    //                            if (pt1y - lastPositionOfRight < textHeight) {//如果计算出的pt1y的位置减去上一个labley的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
    //                                pt2y = pt1y + (textHeight - (pt1y - lastPositionOfRight));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置8,则间距只有pt1y-lastPositionOfRight=2,还需要加上少的textHeight-(pt1y-lastPositionOfRight)=3才行
    //                            } else {
    //                                pt2y = pt1y;
    //                            }
    //                        }
    //                        lastPositionOfRight = pt2y;//记录上一个lableY方向的位置
    //                        mValuePaint.setTextAlign(Paint.Align.LEFT);
    //
    //                        if (drawXOutside)
    //                            getPaintEntryLabels().setTextAlign(Paint.Align.LEFT);
    //
    //                        labelPtx = pt2x + offset;
    //                        labelPty = pt2y;
    //                    }
    //
    //                    if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) {
    //                        c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint);
    //                        c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint);
    //                    }
    //
    //                    // draw everything, depending on settings
    //                    if (drawXOutside && drawYOutside) {
    //
    //                        drawValue(c,
    //                                formatter,
    //                                value,
    //                                entry,
    //                                0,
    //                                labelPtx,
    //                                labelPty,
    //                                dataSet.getValueTextColor(j));
    //
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight);
    //                        }
    //
    //                    } else if (drawXOutside) {
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f);
    //                        }
    //                    } else if (drawYOutside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet
    //                                .getValueTextColor(j));
    //                    }
    //                }
    //
    //                if (drawXInside || drawYInside) {
    //                    // calculate the text position
    //                    float x = labelRadius * sliceXBase + center.x;
    //                    float y = labelRadius * sliceYBase + center.y;
    //
    //                    mValuePaint.setTextAlign(Paint.Align.CENTER);
    //
    //                    // draw everything, depending on settings
    //                    if (drawXInside && drawYInside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j));
    //
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), x, y + lineHeight);
    //                        }
    //
    //                    } else if (drawXInside) {
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f);
    //                        }
    //                    } else if (drawYInside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j));
    //                    }
    //                }
    //
    //                if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
    //
    //                    Drawable icon = entry.getIcon();
    //
    //                    float x = (labelRadius + iconsOffset.y) * sliceXBase + center.x;
    //                    float y = (labelRadius + iconsOffset.y) * sliceYBase + center.y;
    //                    y += iconsOffset.x;
    //
    //                    Utils.drawImage(
    //                            c,
    //                            icon,
    //                            (int) x,
    //                            (int) y,
    //                            icon.getIntrinsicWidth(),
    //                            icon.getIntrinsicHeight());
    //                }
    //
    //                xIndex++;
    //            }
    //
    //            //画左边
    //            xIndex = entryCount-1;
    //            for (int j = entryCount - 1; j >= 0; j--) {
    //
    //                PieEntry entry = dataSet.getEntryForIndex(j);
    //
    //                if (xIndex == 0)
    //                    angle = 0.f;
    //                else
    //                    angle = absoluteAngles[xIndex - 1] * phaseX;
    //
    //                final float sliceAngle = drawAngles[xIndex];
    //                final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius);
    //
    //                // offset needed to center the drawn text in the slice
    //                final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f;
    //
    //                angle = angle + angleOffset;
    //
    //                final float transformedAngle = rotationAngle + angle * phaseY;
    //
    //                float value = mChart.isUsePercentValuesEnabled() ? entry.getY()
    //                        / yValueSum * 100f : entry.getY();
    //
    //                final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD);
    //                final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD);
    //
    //                final boolean drawXOutside = drawEntryLabels &&
    //                        xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
    //                final boolean drawYOutside = drawValues &&
    //                        yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE;
    //                final boolean drawXInside = drawEntryLabels &&
    //                        xValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
    //                final boolean drawYInside = drawValues &&
    //                        yValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE;
    //
    //                if (drawXOutside || drawYOutside) {
    //
    //                    final float valueLineLength1 = dataSet.getValueLinePart1Length();
    //                    final float valueLineLength2 = dataSet.getValueLinePart2Length();
    //                    final float valueLinePart1OffsetPercentage = dataSet.getValueLinePart1OffsetPercentage() / 100.f;
    //
    //                    float pt2x, pt2y;
    //                    float labelPtx, labelPty;
    //
    //                    float line1Radius;
    //
    //                    if (mChart.isDrawHoleEnabled())
    //                        line1Radius = (radius - (radius * holeRadiusPercent))
    //                                * valueLinePart1OffsetPercentage
    //                                + (radius * holeRadiusPercent);
    //                    else
    //                        line1Radius = radius * valueLinePart1OffsetPercentage;
    //
    //                    final float polyline2Width = dataSet.isValueLineVariableLength()
    //                            ? labelRadius * valueLineLength2 * (float) Math.abs(Math.sin(
    //                            transformedAngle * Utils.FDEG2RAD))
    //                            : labelRadius * valueLineLength2;
    //
    //                    final float pt0x = line1Radius * sliceXBase + center.x;
    //                    final float pt0y = line1Radius * sliceYBase + center.y;
    //
    //                    final float pt1x = labelRadius * (1 + valueLineLength1) * sliceXBase + center.x;
    //                    final float pt1y = labelRadius * (1 + valueLineLength1) * sliceYBase + center.y;
    //
    //                    //左右算法不一样,左边是从下往上排的,即你可以理解为饼图是顺时针方向,从零点排到12点的360度圆形,建议先看else里的,即右边的,方便理解
    //                    if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) {//左边部分
    //                        pt2x = center.x - radius - 5;
    //                        if (lastPositionOfLeft == 0) {//第一个不用管
    //                            pt2y = pt1y;
    //                        } else {
    //                            if (pt1y - lastPositionOfLeft < textHeight) {//如果上一个labley的位置减去计算出的pt1y的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
    //                                pt2y = pt1y + (textHeight - (pt1y - lastPositionOfLeft));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置12,则间距只有lastPositionOfRight-pt1y=2,还需要减去少的textHeight-(lastPositionOfRight-pt1y)=3才行
    //                            } else {
    //                                pt2y = pt1y;
    //                            }
    //                        }
    //                        lastPositionOfLeft = pt2y;//记录上一个lableY方向的位置
    //
    //                        mValuePaint.setTextAlign(Paint.Align.RIGHT);
    //
    //                        if (drawXOutside)
    //                            getPaintEntryLabels().setTextAlign(Paint.Align.RIGHT);
    //
    //                        labelPtx = pt2x - offset;
    //                        labelPty = pt2y;
    //
    //                    } else {//右边部分
    ////                        pt2x = center.x + radius + 5;
    ////                        if (lastPositionOfRight == 0) {//第一个不用管
    ////                            pt2y = pt1y;
    ////                        } else {
    ////                            if (pt1y - lastPositionOfRight < textHeight) {//如果计算出的pt1y的位置减去上一个labley的位置间距小于lable的高度,则需要在计算出的y基础上加上差的间距
    ////                                pt2y = pt1y + (textHeight - (pt1y - lastPositionOfRight));//例如:lable高度5,计算出的pt1y位置10,上一个labley的位置8,则间距只有pt1y-lastPositionOfRight=2,还需要加上少的textHeight-(pt1y-lastPositionOfRight)=3才行
    ////                            } else {
    ////                                pt2y = pt1y;
    ////                            }
    ////                        }
    ////                        lastPositionOfRight = pt2y;//记录上一个lableY方向的位置
    ////                        mValuePaint.setTextAlign(Paint.Align.LEFT);
    ////
    ////                        if (drawXOutside)
    ////                            getPaintEntryLabels().setTextAlign(Paint.Align.LEFT);
    ////
    ////                        labelPtx = pt2x + offset;
    ////                        labelPty = pt2y;
    //                        continue;
    //                    }
    //
    //                    if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) {
    //                        c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint);
    //                        c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint);
    //                    }
    //
    //                    // draw everything, depending on settings
    //                    if (drawXOutside && drawYOutside) {
    //
    //                        drawValue(c,
    //                                formatter,
    //                                value,
    //                                entry,
    //                                0,
    //                                labelPtx,
    //                                labelPty,
    //                                dataSet.getValueTextColor(j));
    //
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight);
    //                        }
    //
    //                    } else if (drawXOutside) {
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f);
    //                        }
    //                    } else if (drawYOutside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet
    //                                .getValueTextColor(j));
    //                    }
    //                }
    //
    //                if (drawXInside || drawYInside) {
    //                    // calculate the text position
    //                    float x = labelRadius * sliceXBase + center.x;
    //                    float y = labelRadius * sliceYBase + center.y;
    //
    //                    mValuePaint.setTextAlign(Paint.Align.CENTER);
    //
    //                    // draw everything, depending on settings
    //                    if (drawXInside && drawYInside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j));
    //
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), x, y + lineHeight);
    //                        }
    //
    //                    } else if (drawXInside) {
    //                        if (j < data.getEntryCount() && entry.getLabel() != null) {
    //                            drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f);
    //                        }
    //                    } else if (drawYInside) {
    //
    //                        drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j));
    //                    }
    //                }
    //
    //                if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
    //
    //                    Drawable icon = entry.getIcon();
    //
    //                    float x = (labelRadius + iconsOffset.y) * sliceXBase + center.x;
    //                    float y = (labelRadius + iconsOffset.y) * sliceYBase + center.y;
    //                    y += iconsOffset.x;
    //
    //                    Utils.drawImage(
    //                            c,
    //                            icon,
    //                            (int) x,
    //                            (int) y,
    //                            icon.getIntrinsicWidth(),
    //                            icon.getIntrinsicHeight());
    //                }
    //
    //                xIndex--;
    //            }
    //
    //            MPPointF.recycleInstance(iconsOffset);
    //        }
    //        MPPointF.recycleInstance(center);
    //        c.restore();
    //    }
    }
    
    • 再创建一个PieChart的子类,重新父类init()方法,由于我是在ViewPager中使用的,顺便处理了下滑动冲突,不需要的同学,可以把onTouchEvent(MotionEvent evt)删掉,代码如下:
    public class MyPieChart extends PieChart {
        PointF downPoint = new PointF();
    
        public MyPieChart(Context context) {
            super(context);
        }
    
        public MyPieChart(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public MyPieChart(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
    
        @Override
        protected void init() {
            super.init();
            //此处把mRenderer替换成我们自己的PieChartRenderer
            mRenderer = new MyPieChartRenderer(this, mAnimator, mViewPortHandler);
        }
    
        @SuppressLint("ClickableViewAccessibility")
        @Override
        public boolean onTouchEvent(MotionEvent evt) {
            switch (evt.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    downPoint.x = evt.getX();
                    downPoint.y = evt.getY();
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (Math.abs(evt.getX() - downPoint.x) > 5 || Math.abs(evt.getY() - downPoint.y) > 5) {
                        getParent().requestDisallowInterceptTouchEvent(true);
                    }
                    break;
            }
            return super.onTouchEvent(evt);
        }
    }
    
    • 至此,就可以使用了,把我们代码中的PieChart都替换成MyPieChart就好了,赶紧试试吧,看有没有达到去除重叠的效果。

    文中的bug已经在MPAndroidChart饼图(PieChart)Value值重叠的解决方法(二)中完美解决了,可以去看看

    相关文章

      网友评论

        本文标题:MPAndroidChart饼图(PieChart)Value值

        本文链接:https://www.haomeiwen.com/subject/nequkftx.html