MPAndroidChart柱状图——显示不同渐变色的柱状图

本来设计图,方方正正的柱图不好嘛~非要加一些奇奇怪怪的需求0-0
在这里插入图片描述
先上图:
在这里插入图片描述

需求大概就是需要渐变色,又要下面底平,上面是圆头的。

正常我们在官方例子里面,我们可以知道.

BarDataSet set1;
set1.setFills(gradientFills);

这样就可以设置渐变色了,但是这里有一个坑需要注意的是,如果是implementation V3.1的版本,这个方法会不存在,所以需要下载源代码然后到自己的库里面去。

OK,好了,剩下就是圆头的事情了。
众所周知,BarChart画画的事情,主要跟它的渲染器有问题,所以去设置渲染器就可以了。

BarChart有个专门做倒角的渲染器.RoundedBarChartRenderer

        RoundedBarChartRenderer roundedBarChartRenderer = new RoundedBarChartRenderer(gBarChart,gBarChart.getAnimator(),gBarChart.getViewPortHandler());
        roundedBarChartRenderer.setmRadius(20f);
        gBarChart.setRenderer(roundedBarChartRenderer);

但是发现问题:这个圆角是四个角,不符合我们的需求啊~
在这里插入图片描述
然后去找BarChartRender类把,画图方法是drawDataSet,我们进行重写它,发现正常走的是drawRect,所以修改它,用Path画出自己需要的图案.

RectF r2 = new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]);
Path path = new Path();
path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);
c.drawPath(path, mRenderPaint);

但是又出现另外一个问题,发现有渐变的时候,走的位置是另外的方法.

dataSet.getFill(pos)
                        .fillRect(
                                c, mRenderPaint,
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j + 2],
                                buffer.buffer[j + 3],
                                isInverted ? Fill.Direction.DOWN : Fill.Direction.UP);

OK,我们进到dataSet.getFill(pos).fillRect()方法,发现执行的也是drawRect方法。
之后我们进行修改可以了。

添加一个xRender类继承BarChartRenderer ,并重写drawDataSet方法,完整的Render


public class xRender extends BarChartRenderer {

    private RectF mBarShadowRectBuffer = new RectF();


    public xRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
        super(chart, animator, viewPortHandler);
        this.mChart = chart;
        mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mHighlightPaint.setColor(Color.rgb(0, 0, 0));
        mHighlightPaint.setAlpha(120);
        mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mShadowPaint.setStyle(Paint.Style.FILL);
        mBarBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBarBorderPaint.setStyle(Paint.Style.STROKE);
    }

    @Override
    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()));

        final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f;

        float phaseX = mAnimator.getPhaseX();
        float phaseY = mAnimator.getPhaseY();

        // draw the bar shadow before the values
        if (mChart.isDrawBarShadowEnabled()) {
            mShadowPaint.setColor(dataSet.getBarShadowColor());

            BarData barData = mChart.getBarData();

            final float barWidth = barData.getBarWidth();
            final float barWidthHalf = barWidth / 2.0f;
            float x;

            for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount());
                 i < count;
                 i++) {

                BarEntry e = dataSet.getEntryForIndex(i);

                x = e.getX();

                mBarShadowRectBuffer.left = x - barWidthHalf;
                mBarShadowRectBuffer.right = x + barWidthHalf;

                trans.rectValueToPixel(mBarShadowRectBuffer);

                if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right))
                    continue;

                if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
                    break;

                mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
                mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();

                c.drawRect(mBarShadowRectBuffer, mShadowPaint);
            }
        }

        // 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);

        final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty();
        final boolean isSingleColor = dataSet.getColors().size() == 1;
        final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency());

        if (isSingleColor) {
            mRenderPaint.setColor(dataSet.getColor());
        }

        for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) {

            if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
                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(pos));
            }
            if (isCustomFill) {
                dataSet.getFill(pos)
                        .fillRectx(
                                c, mRenderPaint,
                                buffer.buffer[j],
                                buffer.buffer[j + 1],
                                buffer.buffer[j + 2],
                                buffer.buffer[j + 3],
                                isInverted ? Fill.Direction.DOWN : Fill.Direction.UP);
            }else {
                RectF r2 = new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                        buffer.buffer[j + 3]);

                Path path = new Path();
                //float数组中4个角分别是左上、右上、右下、左下
                path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);
                c.drawPath(path, mRenderPaint);
            }
            //c.drawRoundRect(r2,50,10,mRenderPaint);
//            c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
//                    buffer.buffer[j + 3], mRenderPaint);

            if (drawBorder) {
                c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
                        buffer.buffer[j + 3], mBarBorderPaint);
            }
        }

    }

    /**
     * 手指点击的半透明灰色修改
     * */
    @Override
    public void drawHighlighted(Canvas c, Highlight[] indices) {
        BarData barData = mChart.getBarData();
        for (Highlight high : indices) {
            IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
            if (set == null || !set.isHighlightEnabled())
                continue;
            BarEntry e = set.getEntryForXValue(high.getX(), high.getY());
            if (!isInBoundsX(e, set))
                continue;
            Transformer trans = mChart.getTransformer(set.getAxisDependency());
            mHighlightPaint.setColor(set.getHighLightColor());
            mHighlightPaint.setAlpha(set.getHighLightAlpha());
            boolean isStack = (high.getStackIndex() >= 0  && e.isStacked()) ? true : false;

            final float y1;
            final float y2;

            if (isStack) {

                if(mChart.isHighlightFullBarEnabled()) {

                    y1 = e.getPositiveSum();
                    y2 = -e.getNegativeSum();

                } else {

                    Range range = e.getRanges()[high.getStackIndex()];

                    y1 = range.from;
                    y2 = range.to;
                }

            } else {
                y1 = e.getY();
                y2 = 0.f;
            }

            prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);

            setHighlightDrawPos(high, mBarRect);
            // c.drawRect(mBarRect, mHighlightPaint);  原父类方法

            Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
            path.addRoundRect(mBarRect,new float[]{50, 50, 50, 50, 0, 0, 0, 0},Path.Direction.CCW);
            c.drawPath(path,mHighlightPaint);

        }
    }
}

在点进去的dataSet.getFill(pos).fillRect()方法添加以下方法。


    public void fillRectx(Canvas c, Paint paint,
                         float left, float top, float right, float bottom,
                         Direction gradientDirection)
    {
        switch (mType)
        {
            case EMPTY:
                return;

            case COLOR:
            {
                if (mFinalColor == null) return;

                if (isClipPathSupported())
                {
                    int save = c.save();

                    c.clipRect(left, top, right, bottom);
                    c.drawColor(mFinalColor);

                    c.restoreToCount(save);
                }
                else
                {
                    // save
                    Paint.Style previous = paint.getStyle();
                    int previousColor = paint.getColor();

                    // set
                    paint.setStyle(Paint.Style.FILL);
                    paint.setColor(mFinalColor);

                    c.drawRect(left, top, right, bottom, paint);

                    // restore
                    paint.setColor(previousColor);
                    paint.setStyle(previous);
                }
            }
            break;

            case LINEAR_GRADIENT:
            {
                if (mGradientColors == null) return;

                LinearGradient gradient = new LinearGradient(
                        (int) (gradientDirection == Direction.RIGHT
                                ? right
                                : gradientDirection == Direction.LEFT
                                ? left
                                : left),
                        (int) (gradientDirection == Direction.UP
                                ? bottom
                                : gradientDirection == Direction.DOWN
                                ? top
                                : top),
                        (int) (gradientDirection == Direction.RIGHT
                                ? left
                                : gradientDirection == Direction.LEFT
                                ? right
                                : left),
                        (int) (gradientDirection == Direction.UP
                                ? top
                                : gradientDirection == Direction.DOWN
                                ? bottom
                                : top),
                        mGradientColors,
                        mGradientPositions,
                        android.graphics.Shader.TileMode.MIRROR);

                paint.setShader(gradient);

                RectF r2 = new RectF(left, top,right,
                        bottom);
                Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
                path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);

                c.drawPath(path, paint);
            }
            break;

            case DRAWABLE:
            {
                if (mDrawable == null) return;

                mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom);
                mDrawable.draw(c);
            }
            break;
        }
    }

使用:搞定~

  xRender roundedBarChartRenderer = new xRender(gBarChart,gBarChart.getAnimator(),gBarChart.getViewPortHandler());
        gBarChart.setRenderer(roundedBarChartRenderer);

这可真是一个神奇的框架~~~

画一个自定义死角弧度的Path:
https://blog.csdn.net/qq_40129067/article/details/108799871

RectF rectF=new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],buffer.buffer[j + 3]);

Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
path.addRoundRect(rectF,new float[]{0, 0, 20, 20, 20, 20, 0, 0},Path.Direction.CCW);
c.drawPath(path,mRenderPaint);

柱图Render画图位置

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值