欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图

程序员文章站 2024-02-23 21:35:52
...

内容描述

a .在柱状图上显示文本
b.间断式显示柱状图

产品原型如下:
MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图
难点描述:
MPAndroidChart 并不支持将文字描述信息展示到柱状图(条形图)上;而且也不支持不从0开始的柱状节点展示。

期望目标:
MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图

代码实现

注意本代码的实现,只针对柱状图(BarChart)

绘制间断柱状图

柱状图的区域描述是通过Barbuffer对象中的buffer数组中的四个元素描述四个坐标(left,top,right,bottom)。
在MPAndroidChart中,设置BarChartEntry的时候,每一个float值都对应者一个柱状图区域,也就是转化一个连续的buffer数组元素(如下图所示)。现在要想描述间断是柱状图,需要两个float值(start,detaY)。因此需要改变其对应的数组元素映射feed(IBarDataSet data)。
MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图

 @Override
    public void feed(IBarDataSet data) {

        float size = data.getEntryCount() * phaseX;
        float barWidthHalf = mBarWidth / 2f;

        for (int i = 0; i < size; i++) {

            BarEntry e = data.getEntryForIndex(i);

            if(e == null)
                continue;

            float x = e.getX();
            float y = e.getY();
            float[] vals = e.getYVals();

            if (!mContainsStacks || vals == null) {
            	...
            } else {

                float posY = 0f;
                float negY = -e.getNegativeSum();
                float yStart = 0f;
                if(e.isPresentOneData()){
                    checkData(vals);
                }

                // fill the stack
                for (int k = 0; k < vals.length; k++) {

                    float value = vals[k];

                    if (value == 0.0f && (posY == 0.0f || negY == 0.0f)) {
                        // Take care of the situation of a 0.0 value, which overlaps a non-zero bar
                        y = value;
                        yStart = y;
                    } else if (value >= 0.0f) {
                        y = posY;
                        yStart = posY + value;
                        posY = yStart;
                    } else {
                        y = negY;
                        yStart = negY + Math.abs(value);
                        negY += Math.abs(value);
                    }

                    float left = x - barWidthHalf;
                    float right = x + barWidthHalf;
                    float bottom, top;

                    if (mInverted) {
                        bottom = y >= yStart ? y : yStart;
                        top = y <= yStart ? y : yStart;
                    } else {
                        top = y >= yStart ? y : yStart;
                        bottom = y <= yStart ? y : yStart;
                    }

                    // multiply the height of the rect with the phase
                    top *= phaseY;
                    bottom *= phaseY;
					//两个float元素对应一个 bar区域
                    if(k==0&&e.isPresentOneData()){

                    }else{
                        addBar(left, top, right, bottom);
                    }
                }
            }
        }

        reset();
    }

绘制文字描述信息

优秀的MPAndroidChart设计的很友好。在DataRenderer接口中预留了一个drawExtras(Canvas c)接口,可以让开发者自定义内容。 而在柱状图上显示文本,就是在该方法中实现业务逻辑。
MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图
参考这现有的DrawValue方法,写一个描述信息的功能

 @Override
    public void drawExtras(Canvas c) {
        // if values are drawn
        List<IBarDataSet> dataSets = mChart.getBarData().getDataSets();

        final float valueOffsetPlus = Utils.convertDpToPixel(4.5f);
        float posOffset = 0f;

        for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) {

            IBarDataSet dataSet = dataSets.get(i);

            if (!dataSet.isDrawDesEnabled())
                continue;

            // apply the text-styling defined by the DataSet
            applyDesTextStyle(dataSet);

            // calculate the correct offset depending on the draw position of
            // the value
            float valueTextHeight = Utils.calcTextHeight(mDesPaint, "8");
            posOffset = valueTextHeight + valueOffsetPlus;


            // get the buffer
            BarBuffer buffer = mBarBuffers[i];

            MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
            iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
            iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);


            int bufferIndex = 0;
            int index = 0;

            while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) {

                BarEntry entry = dataSet.getEntryForIndex(index);

                float[] vals = entry.getYVals();
                float x = (buffer.buffer[bufferIndex] + buffer.buffer[bufferIndex + 2]) / 2f;

                int color = dataSet.getDesTextColor(index);

                if (!mViewPortHandler.isInBoundsRight(x))
                    break;

                if (!mViewPortHandler.isInBoundsY(buffer.buffer[bufferIndex + 3])
                        || !mViewPortHandler.isInBoundsLeft(x))
                    continue;
                //核心代码 如果开始描述文字的功能,则渲染文字
                if (dataSet.isDrawDesEnabled()) {
                    //检查空间
                    if(buffer.buffer[bufferIndex+3]-buffer.buffer[bufferIndex+1]>4+posOffset){
                        drawDes(c, entry.getDes(), x, buffer.buffer[bufferIndex + 3] - posOffset,
                                color);
                    }else {
                        drawDes(c, entry.getDes(), x, buffer.buffer[bufferIndex + 3] +
                                        posOffset,
                                color);
                    }

                }

                // draw stack values
                bufferIndex = vals == null ? bufferIndex + 4 : bufferIndex + 4 * (entry.isPresentOneData()?1:vals.length);
                index++;
            }

            MPPointF.recycleInstance(iconsOffset);
        }
    }

处理触摸事件

在MPAndroidChart中,onTouch事件最终会作用到Range对象中。而且在定义BarChartEntry时,如果传入了Float[]数组,那么每个元素都会转化为一个Range对象。但是但进行间断是表示数据时,则需要两个float来描述一个range对象。具体修改如下所示:
MPAndroidchart自定义样式二在柱状图上显示文本和间断式显示柱状图

使用

ArrayList<BarEntry> barEntries = new ArrayList<>();
        //1.链式调用
        barEntries.add(new BarEntry(1, new float[]{ 0, 0.21111f })		
        //2.设置是否是float[2] 展示一个数据
                .setPresentOneData(true)
      	//3. 设置文本描述信息         
                .setmDes("12.3%"));
        barEntries.add(new BarEntry(2,new float[]{0.11111f,0.3f})
                .setPresentOneData(true)
                .setmDes("12.3%"));
       	...
       	...
        barEntries.add(new BarEntry(6, new float[]{1,1.3f})
                .setPresentOneData(true)
                .setmDes("12.3%"));

        BarDataSet barDataSet = new BarDataSet(barEntries, "error times").setDrawDesEnable(true);
        //设置描述字体的颜色
        barDataSet.setmDesColor(Color.RED);

代码传送门

相关标签: 开源项目