MPAndroidChart使用详解

转自 https://blog.csdn.net/yuguangwu123/article/details/54575631

MPAndroidChart架构分析:

MPChart是github上最受欢迎的一款开源图标控件,可高度定制化。最近项目需求,需要自己造轮子,就在MPChart基础上进行定制。过后感觉比较好用,但是中间也走了些弯路,总结了一下使用方法,分析了下这个开源框架的架构,分享给大家。

有几种集成方式, Gradle dependency (recommended),Maven,jar file only,clone whole repository(因为需要定制,直接在源码里修改)。项目主页https://github.com/PhilJay/MPAndroidChart

丰富多样的图表效果:(单,双,多)折线图,曲线图,饼状图,散点图,柱状图

项目结构:

Charts里放了各种图表的基类,提供图表参数设定入口。

通过获得的对象可设定图标数据集合

是否支持缩放

图标值选择事件监听

对XY轴绘制的定制:刻度值的显示格式,间隔,刻度数目,网格背景

设定图表动画样式

Data里放了各类图表对应的数据初始化集合类:通过使用泛型和通配符对数据集合

 通过初始化获得对象可设定绘制图表线、点、圆的半径、对应颜色、显示数据格式,内容。

Renderer(渲染)里放了对各类图标数据集合以及XY轴数据的绘制

Listener里放的是图表的点击、触摸事件的处理。

总的来讲,chart初始化的时候就使用泛型和通配符定义了数据集合,继承图表的基类,为图标的渲染初始化了render,对点击事件注册了监听。用Barchart举个栗子:

继承柱状图折线图的基类BarLineChartBase,限定数据集合为BarData。

BarLineChartBase,因为LineChart、BubbleChart、ScatterChart、CandleChart都是继承自此类,在限定数据集合的时候,使用泛型和通配符参数化类型。

继承图标基类Chart<T>,同样是参数化数据集合类型。

以BarChart为例:

当新建Barchart对象时,父类Chart的构造函数会调用init(),在Barchart中重载

  @Override

    protected void init() {

        super.init();

        mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler);

        setHighlighter(new BarHighlighter(this));

        getXAxis().setSpaceMin(0.5f);

        getXAxis().setSpaceMax(0.5f);

}

在此获取柱状图的渲染器mRenderer

继而可以通过Barchart的对象设定柱状图的刻度显示,是否支持点击、拖动、缩放的监听,以及数据集合。

当设定数据集合时,Chart继承自ViewGroup,会调用notifyDataSetChanged()刷新图表,setData(T data)在Chart中的实现:

  public void setData(T data) {

        mData = data;

        mOffsetsCalculated = false;

        if (data == null) {

            return;

        }

        // calculate how many digits are needed

        setupDefaultFormatter(data.getYMin(), data.getYMax());

        for (IDataSet set : mData.getDataSets()) {

            if (set.needsFormatter() || set.getValueFormatter() == mDefaultValueFormatter)

                set.setValueFormatter(mDefaultValueFormatter);

        }

        // let the chart know there is new data

        notifyDataSetChanged();

    }

在继承的子类中重写notifyDataSetChanged(),在BarLineChartBase中,已经初始化图表的数据集合以及设定横纵轴、图表显示参数,在刷新图表时在OnDraw()中调用横纵轴以及图表内容的渲染对象对图标进行绘制。

      @Override

    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

…………

        if (mAxisLeft.isEnabled())

            mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted());

        if (mAxisRight.isEnabled())

            mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted());

        if (mXAxis.isEnabled())

            mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false);

        mXAxisRenderer.renderAxisLine(canvas);

        mAxisRendererLeft.renderAxisLine(canvas);

        mAxisRendererRight.renderAxisLine(canvas);

        if (mAutoScaleMinMaxEnabled) {

            autoScale();

        }

        mXAxisRenderer.renderGridLines(canvas);

        mAxisRendererLeft.renderGridLines(canvas);

        mAxisRendererRight.renderGridLines(canvas);

        …………

//渲染柱状图

        mRenderer.drawData(canvas);

       …………

        mXAxisRenderer.renderAxisLabels(canvas);

        mAxisRendererLeft.renderAxisLabels(canvas);

        mAxisRendererRight.renderAxisLabels(canvas);

        mRenderer.drawValues(canvas);

        mLegendRenderer.renderLegend(canvas);

        drawDescription(canvas);

        drawMarkers(canvas);

    }

在渲染器中,以BarChartRenderer图表内容的渲染为例:

 @Override

    public void drawData(Canvas c) {

        BarData barData = mChart.getBarData();

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

            IBarDataSet set = barData.getDataSetByIndex(i);

            if (set.isVisible()) {

                drawDataSet(c, set, i);

            }

        }

}

//绘制数据集合

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

        …………

        // 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 isSingleColor = dataSet.getColors().size() == 1;

        if (isSingleColor) {

            mRenderPaint.setColor(dataSet.getColor());

        }

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

            …………

//柱状图柱子绘制

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

            }

        }

}

BarChart具体使用示例:

 贴上代码:

private void initBarchart(){

   /**

初始化以后,可以通过对象设置图标的横纵坐标轴的刻度值以及格式,图标背景,是否支持点击事件,缩放等。

   **/

   barChart = (BarChart)ndViewById(R.id.barchart);

    barChart.setMaxVisibleValueCount(60);

//设定图标网格背景

    barChart.setDrawGridBackground(false);

//柱状图值显示格式化,可自定义

    IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(barChart);

//图标X轴自定义,包括X轴位置、刻度值格式、颜色,网格绘制,背景色,刻度数目,最大最小值限定

    XAxis xAxis = barChart.getXAxis();

    xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);

    xAxis.setDrawGridLines(false);

    xAxis.setGranularity(1f); // only intervals of 1 day

    xAxis.setLabelCount(6);

    xAxis.setValueFormatter(new IAxisValueFormatter() {

        @Override

        public String getFormattedValue(float value, AxisBase axis) {

            //根据横坐标刻度值来赋值

        int location = Float.valueOf(value).intValue();

            location=(location>=7?7:location);

            if(location>=0&&location<7&&location<list.size()&&list.get(location).getY()!=-1)

                return xVals[location];

            else

                return "";

        }

        @Override

        public int getDecimalDigits() {

            return 0;

        }

    });

    //图例,对图表颜色种类的注释

    barChart.getLegend().setEnabled(false);

//是否显示图标的标题

    barChart.getDescription().setEnabled(false);

//是否支持图标点击、触摸时间

    barChart.setTouchEnabled(false);

//是否支持拖动

    barChart.setDragEnabled(false);

    //柱状图左侧Y轴描述,同X轴设定方式

    YAxis leftAxis = barChart.getAxisLeft();

    leftAxis.setValueFormatter(new IAxisValueFormatter() {

        @Override

        public String getFormattedValue(float value, AxisBase axis) {

            return Float.valueOf(value).intValue()>0?Float.valueOf(value).intValue()+"%":"0";

        }

        @Override

        public int getDecimalDigits() {

            return 1;

        }

    });

    leftAxis.setTypeface(Typeface.DEFAULT);

    leftAxis.setDrawGridLines(true);//是否绘制柱状图纵轴网格线

    leftAxis.setSpaceTop(100f);

    leftAxis.setLabelCount(10);//纵轴刻度数目

    leftAxis.setAxisMaximum(100f);//刻度值最大值

    leftAxis.setAxisMinimum(0f);  //刻度值最小值

leftAxis.setDrawAxisLine(false);

       leftAxis.setGridColor(getActivity().getResources().getColor(R.color.line_gray));//纵轴网格线背景色

    leftAxis.setGridLineWidth(1);//纵轴网格线宽度

//是否绘制右侧纵轴

    barChart.getAxisRight().setEnabled(false);

//是否支持缩放

barChart.setScaleEnabled(false);

    barChart.setPinchZoom(false);

    //当数据列表为空时默认值显示

barChart.setNoDataText("");

}

private void setBarchartData(){

for(int i = 1;i<10;i++)

        list.add(new BarEntry(1,1));

    //设定默认值集合

    BarDataSet dataSet = new BarDataSet(list,"");

    dataSet.setHighlightEnabled(false);

    dataSet.setDrawValues(false);//是否在图表上显示具体值

    dataSet.setColors(VORDIPLOM_COLORS);//设定图表数据绘制颜色

    

    //对绘制的值格式化输出

    dataSet.setValueFormatter(new IValueFormatter() {

    @Override

    public String getFormattedValue(float value, Entry entry, int    dataSetIndex, ViewPortHandler viewPortHandler) {

        DecimalFormat fnum = new DecimalFormat("##0.00");

        return fnum.format(maxvalue.get(entry.getX())+1);

    }

});

    BarData data = new BarData(dataSet);

    data.setBarWidth(0.5f);

    //设定图标数据集合

    barChart.setData(data);

}

总结:

MPAndroidChart支持对图表横纵轴刻度数目,刻度值格式化,图表数据集合颜色,数据格式化,图例说明等高度定制。在现有开放的api上已经能满足大部分定制图表的需求,如果在项目开发过程中有特殊要求需要深度定制,就需要了解这个图标绘制的一个流程还有监听的处理。希望这篇文章能对大家有帮助。
---------------------
作者:yuguangwu123
来源:CSDN
原文:https://blog.csdn.net/yuguangwu123/article/details/54575631
版权声明:本文为博主原创文章,转载请附上博文链接!

发布了21 篇原创文章 · 获赞 5 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/linchuanzhi_886/article/details/88943085