【问题标题】:MPAndroidChart - Round edged bar chartMPAndroidChart - 圆边条形图
【发布时间】:2015-06-10 15:40:57
【问题描述】:

我正在尝试为我使用 MPAndroidChart 的 android 应用程序创建一个如下所示的图表。我无法弄清楚如何将条形图的边缘设置为圆边。它总是以方形边缘出现。

那么你能建议我该怎么做吗?

提前感谢您的帮助。

【问题讨论】:

    标签: android mpandroidchart


    【解决方案1】:

    我尝试结合@mallaudin 和@Janusz Hain 代码。现在可以用了,谢谢!!! 这是我的代码

    public class CustomBarChartRender extends BarChartRenderer {
    
    private RectF mBarShadowRectBuffer = new RectF();
    
    private int mRadius;
    
    public CustomBarChartRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
        super(chart, animator, viewPortHandler);
    }
    
    public void setRadius(int mRadius) {
        this.mRadius = mRadius;
    }
    
    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
    
        Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
        mBarBorderPaint.setColor(dataSet.getBarBorderColor());
        mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));
        mShadowPaint.setColor(dataSet.getBarShadowColor());
        boolean drawBorder = dataSet.getBarBorderWidth() > 0f;
    
        float phaseX = mAnimator.getPhaseX();
        float phaseY = mAnimator.getPhaseY();
    
        if (mChart.isDrawBarShadowEnabled()) {
            mShadowPaint.setColor(dataSet.getBarShadowColor());
    
            BarData barData = mChart.getBarData();
    
            float barWidth = barData.getBarWidth();
            float barWidthHalf = barWidth / 2.0f;
            float x;
    
            int i = 0;
            double count = Math.min(Math.ceil((int) (double) ((float) dataSet.getEntryCount() * phaseX)), dataSet.getEntryCount());
            while (i < count) {
    
                BarEntry e = dataSet.getEntryForIndex(i);
    
                x = e.getX();
    
                mBarShadowRectBuffer.left = x - barWidthHalf;
                mBarShadowRectBuffer.right = x + barWidthHalf;
    
                trans.rectValueToPixel(mBarShadowRectBuffer);
    
                if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
                    i++;
                    continue;
                }
    
                if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
                    break;
    
                mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
                mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();
    
                c.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint);
                i++;
            }
        }
    
        // initialize the buffer
        BarBuffer buffer = mBarBuffers[index];
        buffer.setPhases(phaseX, phaseY);
        buffer.setDataSet(index);
        buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
        buffer.setBarWidth(mChart.getBarData().getBarWidth());
    
        buffer.feed(dataSet);
    
        trans.pointValuesToPixel(buffer.buffer);
    
        boolean isSingleColor = dataSet.getColors().size() == 1;
    
        if (isSingleColor) {
            mRenderPaint.setColor(dataSet.getColor());
        }
    
        int j = 0;
        while (j < buffer.size()) {
    
            if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
                j += 4;
                continue;
            }
    
            if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                break;
    
            if (!isSingleColor) {
                // Set the color for the currently drawn value. If the index
                // is out of bounds, reuse colors.
                mRenderPaint.setColor(dataSet.getColor(j / 4));
            }
    
            if (dataSet.getGradientColor() != null) {
                GradientColor gradientColor = dataSet.getGradientColor();
                mRenderPaint.setShader(new LinearGradient(
                        buffer.buffer[j],
                        buffer.buffer[j + 3],
                        buffer.buffer[j],
                        buffer.buffer[j + 1],
                        gradientColor.getStartColor(),
                        gradientColor.getEndColor(),
                        android.graphics.Shader.TileMode.MIRROR));
            }
    
            if (dataSet.getGradientColors() != null) {
                mRenderPaint.setShader(new LinearGradient(
                        buffer.buffer[j],
                        buffer.buffer[j + 3],
                        buffer.buffer[j],
                        buffer.buffer[j + 1],
                        dataSet.getGradientColor(j / 4).getStartColor(),
                        dataSet.getGradientColor(j / 4).getEndColor(),
                        Shader.TileMode.MIRROR));
            }
            Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                    buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
            c.drawPath(path2, mRenderPaint);
            if (drawBorder) {
                Path path = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                        buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
                c.drawPath(path, mBarBorderPaint);
            }
            j += 4;
        }
    
    }
    
    private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
        float top = rect.top;
        float left = rect.left;
        float right = rect.right;
        float bottom = rect.bottom;
        Path path = new Path();
        if (rx < 0) rx = 0;
        if (ry < 0) ry = 0;
        float width = right - left;
        float height = bottom - top;
        if (rx > width / 2) rx = width / 2;
        if (ry > height / 2) ry = height / 2;
        float widthMinusCorners = (width - (2 * rx));
        float heightMinusCorners = (height - (2 * ry));
    
        path.moveTo(right, top + ry);
        if (tr)
            path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
        else {
            path.rLineTo(0, -ry);
            path.rLineTo(-rx, 0);
        }
        path.rLineTo(-widthMinusCorners, 0);
        if (tl)
            path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
        else {
            path.rLineTo(-rx, 0);
            path.rLineTo(0, ry);
        }
        path.rLineTo(0, heightMinusCorners);
    
        if (bl)
            path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        else {
            path.rLineTo(0, ry);
            path.rLineTo(rx, 0);
        }
    
        path.rLineTo(widthMinusCorners, 0);
        if (br)
            path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
        else {
            path.rLineTo(rx, 0);
            path.rLineTo(0, -ry);
        }
    
        path.rLineTo(0, -heightMinusCorners);
    
        path.close();//Given close, last lineto can be removed.
    
        return path;
    }}
    

    在其他类:

    CustomBarChartRender barChartRender = new CustomBarChartRender(barChart,barChart.getAnimator(), barChart.getViewPortHandler());
        barChartRender.setRadius(20);
        barChart.setRenderer(barChartRender);
    

    【讨论】:

    • 我得到“java.lang.NullPointerException: Attempt to read from null array at apps.simple.custom.CustomBarChartRender.drawDataSet(CustomBarChartRender.java:85)”
    • 在设置渲染器之前调用 barChartRender.initBuffers()
    • 这行得通。但是我有一个问题,当我点击栏时。圆形条形图正在转换为方形。如何处理。当我单击每个条时,我不希望条变为方形。
    • @duc tan ,我想为雷达图转角,可以吗?
    • 有用的内容。谢谢
    【解决方案2】:

    我已经实现了一个解决方案,可以直接在库本身上实现这一点。

    首先创建一个 attrs.xml 添加一个新属性以在图表视图上使用。像这样的:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="BarChart">
            <attr name="radius" format="integer" />
        </declare-styleable>
    </resources>
    

    然后在 BarChartRenderer 上编辑名为 drawDataSet 的方法:

    protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) {
    
        Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
    
        mShadowPaint.setColor(dataSet.getBarShadowColor());
    
        float phaseX = mAnimator.getPhaseX();
        float phaseY = mAnimator.getPhaseY();
    
        List<BarEntry> entries = dataSet.getYVals();
    
        // initialize the buffer
        BarBuffer buffer = mBarBuffers[index];
        buffer.setPhases(phaseX, phaseY);
        buffer.setBarSpace(dataSet.getBarSpace());
        buffer.setDataSet(index);
        buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
    
        buffer.feed(entries);
    
        trans.pointValuesToPixel(buffer.buffer);
    
        // if multiple colors
        if (dataSet.getColors().size() > 1) {
    
            for (int j = 0; j < buffer.size(); j += 4) {
    
                if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                    continue;
    
                if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                    break;
    
                if (mChart.isDrawBarShadowEnabled()) {
                    if (mRadius > 0)
                        c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
                                buffer.buffer[j + 2],
                                mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                    else
                        c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
                                buffer.buffer[j + 2],
                                mViewPortHandler.contentBottom(), mShadowPaint);
                }
    
                // Set the color for the currently drawn value. If the index
                // is
                // out of bounds, reuse colors.
                mRenderPaint.setColor(dataSet.getColor(j / 4));
                if (mRadius > 0)
                    c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                            buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
                else
                    c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                            buffer.buffer[j + 3], mRenderPaint);
            }
        } else {
    
            mRenderPaint.setColor(dataSet.getColor());
    
            for (int j = 0; j < buffer.size(); j += 4) {
    
                if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                    continue;
    
                if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                    break;
    
                if (mChart.isDrawBarShadowEnabled()) {
                    if (mRadius > 0)
                        c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
                                buffer.buffer[j + 2],
                                mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                    else
                        c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                buffer.buffer[j + 3], mRenderPaint);
                }
    
                if (mRadius > 0)
                    c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                            buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
                else
                    c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                            buffer.buffer[j + 3], mRenderPaint);
            }
        }
    }
    

    通过这样做,您更改了矩形,但没有更改其突出显示,因此请在 drawHighlighted 方法中更改以下代码:

    if (mRadius > 0)
          c.drawRoundRect(mBarRect, mRadius, mRadius, mHighlightPaint);
    else
          c.drawRect(mBarRect, mHighlightPaint);
    

    要从 xml 文件中获取属性到此渲染中,您还需要添加一个 set 方法:

    public void setRadius (int radius) {
            mRadius = radius;
    }
    

    最后在 BarChart 对象上新建一个构造函数来获取半径属性:

    public BarChart(Context context, AttributeSet attrs) {
            super(context, attrs);
            mRadius = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto", "radius", 0);
            ((BarChartRenderer)mRenderer).setRadius(mRadius);
        }
    

    瞧!快乐编码:)

    【讨论】:

    • 使用这种方法只圆角是有原因的吗?
    【解决方案3】:

    从 MPAndroidChart 的最后代码创建了一个完整的要点

    https://gist.github.com/xanscale/e971cc4f2f0712a8a3bcc35e85325c27

    【讨论】:

    • 你能显示你调用这个要点的代码吗?我不知道您将如何将数据传递给此 RoundedBarChart 类,并且此代码是否会在水平条形图中为条形图的负值起作用?
    • 你可以像普通的BarChart一样使用,只是将drawRect替换为drawRoundRect
    【解决方案4】:

    为此,您需要自定义 BarchartRenderer 类....

    第 1 步

    创建一个自定义类(如果您没有将 mpchart 添加为模块)将 BarchartRenderer 类中的所有代码复制粘贴到您的自定义类中。 现在在你的自定义类中用我的方法替换你的 drawDataSet 方法.....

    第 2 步

    然后 setRender 到你刚刚创建的自定义类。

    用于设置渲染 Java 代码的 Kotlin 代码将有点相同。

    最终享受

    BarChartCustomRenderer customRenderer = BarChartCustomRenderer(mDashBoardBinding.topperChart, mDashBoardBinding.topperChart.getAnimator(), mDashBoardBinding.topperChart.getViewPortHandler());
    
    topperChart.setRenderer(customRenderer);
    

    drawDataSet

    protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
    
                Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
    
                mShadowPaint.setColor(dataSet.getBarShadowColor());
    
                float phaseX = mAnimator.getPhaseX();
                float phaseY = mAnimator.getPhaseY();
    
    
                // initialize the buffer
                BarBuffer buffer = mBarBuffers[index];
                buffer.setPhases(phaseX, phaseY);
                buffer.setDataSet(index);
                buffer.setBarWidth(mChart.getBarData().getBarWidth());
                buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
    
                buffer.feed(dataSet);
    
                trans.pointValuesToPixel(buffer.buffer);
    
                // if multiple colors
                if (dataSet.getColors().size() > 1) {
    
                    for (int j = 0; j < buffer.size(); j += 4) {
    
                        if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                            continue;
    
                        if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                            break;
    
                        if (mChart.isDrawBarShadowEnabled()) {
                            if (mRadius > 0)
                                c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
                                        buffer.buffer[j + 2],
                                        mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                            else
                                c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
                                        buffer.buffer[j + 2],
                                        mViewPortHandler.contentBottom(), mShadowPaint);
                        }
    
                        // Set the color for the currently drawn value. If the index
                        // is
                        // out of bounds, reuse colors.
                        mRenderPaint.setColor(dataSet.getColor(j / 4));
                        if (mRadius > 0)
                            c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                    buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
                        else
                            c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                    buffer.buffer[j + 3], mRenderPaint);
                    }
                } else {
    
                    mRenderPaint.setColor(dataSet.getColor());
    
                    for (int j = 0; j < buffer.size(); j += 4) {
    
                        if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                            continue;
    
                        if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                            break;
    
                        if (mChart.isDrawBarShadowEnabled()) {
                            if (mRadius > 0)
                                c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
                                        buffer.buffer[j + 2],
                                        mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                            else
                                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                        buffer.buffer[j + 3], mRenderPaint);
                        }
    
                        if (mRadius > 0)
                            c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                    buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
                        else
                            c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                    buffer.buffer[j + 3], mRenderPaint);
                    }
                }
            }
    

    【讨论】:

    • 您好,刚刚查看了您的评论...让我知道您是否还需要任何帮助
    【解决方案5】:

    1)添加以下类:

    public class RoundedBarChart extends BarChartRenderer {
    
    
        public RoundedBarChart(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
            super(chart, animator, viewPortHandler);
        }
    
        private float mRadius=5f;
    
        public void setmRadius(float mRadius) {
            this.mRadius = mRadius;
        }
    
        @Override
        protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
    
         
                Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
    
                mShadowPaint.setColor(dataSet.getBarShadowColor());
    
                float phaseX = mAnimator.getPhaseX();
                float phaseY = mAnimator.getPhaseY();
    
    
    
                if(mBarBuffers!=null){
                    // initialize the buffer
                    BarBuffer buffer = mBarBuffers[index];
                    buffer.setPhases(phaseX, phaseY);
                    buffer.setDataSet(index);
                    buffer.setBarWidth(mChart.getBarData().getBarWidth());
                    buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
    
                    buffer.feed(dataSet);
    
                    trans.pointValuesToPixel(buffer.buffer);
    
                    // if multiple colors
                    if (dataSet.getColors().size() > 1) {
    
                        for (int j = 0; j < buffer.size(); j += 4) {
    
                            if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                                continue;
    
                            if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                                break;
    
                            if (mChart.isDrawBarShadowEnabled()) {
                                if (mRadius > 0)
                                    c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(), buffer.buffer[j + 2], mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                                else
                                    c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), buffer.buffer[j + 2], mViewPortHandler.contentBottom(), mShadowPaint);
                            }
    
                            // Set the color for the currently drawn value. If the index
                            // is
                            // out of bounds, reuse colors.
                            mRenderPaint.setColor(dataSet.getColor(j / 4));
                            if (mRadius > 0){
    
                                Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
                                c.drawPath(path,mRenderPaint);
                            }
                            else
                                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint);
    
    
                        }
                    } else {
    
                        mRenderPaint.setColor(dataSet.getColor());
    
                        for (int j = 0; j < buffer.size(); j += 4) {
    
                            if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                                continue;
    
                            if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                                break;
    
                            if (mChart.isDrawBarShadowEnabled()) {
                                if (mRadius > 0)
                                    c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
                                            buffer.buffer[j + 2],
                                            mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
                                else
                                    c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                            buffer.buffer[j + 3], mRenderPaint);
                            }
    
                            if (mRadius > 0){
                                Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
                                c.drawPath(path,mRenderPaint);
                            }
                            else
                                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                                        buffer.buffer[j + 3], mRenderPaint);
                        }
                    }
                }
            
        }
        public static Path RoundedRect(
                float left, float top, float right, float bottom, float rx, float ry,
                boolean tl, boolean tr, boolean br, boolean bl
        ){
            Path path = new Path();
            if (rx < 0) rx = 0;
            if (ry < 0) ry = 0;
            float width = right - left;
            float height = bottom - top;
            if (rx > width / 2) rx = width / 2;
            if (ry > height / 2) ry = height / 2;
            float widthMinusCorners = (width - (2 * rx));
            float heightMinusCorners = (height - (2 * ry));
    
            path.moveTo(right, top + ry);
            if (tr)
                path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
            else{
                path.rLineTo(0, -ry);
                path.rLineTo(-rx,0);
            }
            path.rLineTo(-widthMinusCorners, 0);
            if (tl)
                path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
            else{
                path.rLineTo(-rx, 0);
                path.rLineTo(0,ry);
            }
            path.rLineTo(0, heightMinusCorners);
    
            if (bl)
                path.rQuadTo(0, ry, rx, ry);//bottom-left corner
            else{
                path.rLineTo(0, ry);
                path.rLineTo(rx,0);
            }
    
            path.rLineTo(widthMinusCorners, 0);
            if (br)
                path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
            else{
                path.rLineTo(rx,0);
                path.rLineTo(0, -ry);
            }
    
            path.rLineTo(0, -heightMinusCorners);
    
            path.close();//Given close, last lineto can be removed.
    
            return path;
        }
    }
    

    2) 使用barChart.renderer = RoundedBarChart(barChart, barChart.animator, barChart.viewPortHandler)

    【讨论】:

      【解决方案6】:

      我已经为实际库创建了基于上述的类(它有不同的绘图代码)-v3.1.0-alpha

      class RoundedBarChartRenderer(chart: BarDataProvider,
                                animator: ChartAnimator,
                                viewPortHandler: ViewPortHandler,
                                private val mRadius: Float) :
          BarChartRenderer(chart, animator, viewPortHandler) {
      
      private val mBarShadowRectBuffer = RectF()
      
      override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) {
      
          if (c == null || dataSet == null) return
      
          val trans = mChart.getTransformer(dataSet.axisDependency)
      
          mBarBorderPaint.color = dataSet.barBorderColor
          mBarBorderPaint.strokeWidth = Utils.convertDpToPixel(dataSet.barBorderWidth)
      
          val drawBorder = dataSet.barBorderWidth > 0f
      
          val phaseX = mAnimator.phaseX
          val phaseY = mAnimator.phaseY
      
          // draw the bar shadow before the values
          if (mChart.isDrawBarShadowEnabled) {
              mShadowPaint.color = dataSet.barShadowColor
      
              val barData = mChart.barData
      
              val barWidth = barData.barWidth
              val barWidthHalf = barWidth / 2.0f
              var x: Float
      
              var i = 0
              val count = Math.min(Math.ceil((dataSet.entryCount.toFloat() * phaseX).toDouble()).toInt(), dataSet.entryCount)
              while (i < count) {
      
                  val e = dataSet.getEntryForIndex(i)
      
                  x = e.x
      
                  mBarShadowRectBuffer.left = x - barWidthHalf
                  mBarShadowRectBuffer.right = x + barWidthHalf
      
                  trans.rectValueToPixel(mBarShadowRectBuffer)
      
                  if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
                      i++
                      continue
                  }
      
                  if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
                      break
      
                  mBarShadowRectBuffer.top = mViewPortHandler.contentTop()
                  mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom()
      
                  c.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint)
                  i++
              }
          }
      
          // initialize the buffer
          val buffer = mBarBuffers[index]
          buffer.setPhases(phaseX, phaseY)
          buffer.setDataSet(index)
          buffer.setInverted(mChart.isInverted(dataSet.axisDependency))
          buffer.setBarWidth(mChart.barData.barWidth)
      
          buffer.feed(dataSet)
      
          trans.pointValuesToPixel(buffer.buffer)
      
          val isSingleColor = dataSet.colors.size == 1
      
          if (isSingleColor) {
              mRenderPaint.color = dataSet.color
          }
      
          var j = 0
          while (j < buffer.size()) {
      
              if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
                  j += 4
                  continue
              }
      
              if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
                  break
      
              if (!isSingleColor) {
                  // Set the color for the currently drawn value. If the index
                  // is out of bounds, reuse colors.
                  mRenderPaint.color = dataSet.getColor(j / 4)
              }
      
              if (dataSet.gradientColor != null) {
                  val gradientColor = dataSet.gradientColor
                  mRenderPaint.shader = LinearGradient(
                          buffer.buffer[j],
                          buffer.buffer[j + 3],
                          buffer.buffer[j],
                          buffer.buffer[j + 1],
                          gradientColor.startColor,
                          gradientColor.endColor,
                          android.graphics.Shader.TileMode.MIRROR)
              }
      
              if (dataSet.gradientColors != null) {
                  mRenderPaint.shader = LinearGradient(
                          buffer.buffer[j],
                          buffer.buffer[j + 3],
                          buffer.buffer[j],
                          buffer.buffer[j + 1],
                          dataSet.getGradientColor(j / 4).startColor,
                          dataSet.getGradientColor(j / 4).endColor,
                          Shader.TileMode.MIRROR)
              }
      
      
              c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                      buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint)
      
              if (drawBorder) {
                  c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                          buffer.buffer[j + 3]), mRadius, mRadius, mBarBorderPaint)
              }
              j += 4
          }
      }
      

      }

      【讨论】:

        【解决方案7】:

        您可以使用@Xan 提供的要点,如果您希望两边都是圆形的,您可以实现要点并为条形图视图提供以下属性

        barChartView.axisLeft.axisMinimum = 0f;
        

        这将使两边都变圆。

        【讨论】:

        • 你的单行代码没有生效让Bar的两个角都变圆了!!!!!!
        • 您是否也实现了@Xan 提供的要点?实现该要点将为您提供一侧圆形边缘,添加这行代码将使其两侧圆形。
        【解决方案8】:

        上面的答案是对的,但是如果图表有负值则不起作用

        我选择了圆角矩形代码形式this 答案。

        步骤

        1. BarChartRenderer类中添加如下方法

          /**
           * @param rect rectangle to be rounded
           * @param rx   radius x
          * @param ry   radius y
          * @param tl   true - for rounding top-left corner
          * @param tr   true - for rounding top-right corner
          * @param br   true - for rounding bottom-right corner
          * @param bl   true - for rounding bottom-left corner
          * @return path
          */
          private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
          float top = rect.top;
          float left = rect.left;
          float right = rect.right;
          float bottom = rect.bottom;
          Path path = new Path();
          if (rx < 0) rx = 0;
          if (ry < 0) ry = 0;
          float width = right - left;
          float height = bottom - top;
          if (rx > width / 2) rx = width / 2;
          if (ry > height / 2) ry = height / 2;
          float widthMinusCorners = (width - (2 * rx));
          float heightMinusCorners = (height - (2 * ry));
          
          path.moveTo(right, top + ry);
          if (tr)
              path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
          else {
              path.rLineTo(0, -ry);
              path.rLineTo(-rx, 0);
          }
          path.rLineTo(-widthMinusCorners, 0);
          if (tl)
              path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
          else {
              path.rLineTo(-rx, 0);
              path.rLineTo(0, ry);
          }
          path.rLineTo(0, heightMinusCorners);
          
          if (bl)
              path.rQuadTo(0, ry, rx, ry);//bottom-left corner
          else {
              path.rLineTo(0, ry);
              path.rLineTo(rx, 0);
          }
          
          path.rLineTo(widthMinusCorners, 0);
          if (br)
              path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
          else {
              path.rLineTo(rx, 0);
              path.rLineTo(0, -ry);
          }
          
          path.rLineTo(0, -heightMinusCorners);
          
          path.close();//Given close, last lineto can be removed.
          
          return path;
          }
          
        2. drawDataSet(Canvas c, IBarDataSet dataSet, int index)方法中,将alldrawRoundRect方法替换为以下代码

           Path path = roundRect(yourRect, yourRadius, yourRadius, true, true, false, false);
                          canvas.drawPath(path, yourPaint);
          

        【讨论】:

        • 谢谢。在我的例子中,Y 轴总是有正值和负值。为了更好地理解,您可以查看 MPChart 中的 Stacked Bar Chart Negative 示例。我做了一些事情,它看起来像这样。 imgur.com/a/wDeLu 我希望零线正确对齐。对此有任何想法吗?
        • 我需要使用 (true,true,false,false) 调用 roundRect 方法来获取正值和负值 (false,false,true,true)。如何在 drawRectmethod() 中获取 Y 轴值,以便我可以根据这些值进行检查。我说的对吗?
        • @DroidLearner 我有同样的问题要解决,你解决了这个问题吗?如果可以,请分享代码sn-p或程序谢谢。
        猜你喜欢
        • 1970-01-01
        • 2016-05-08
        • 2023-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-15
        • 1970-01-01
        相关资源
        最近更新 更多