基于MPAndroidChart的自定义LineChart(一)----节点绘制叉号+分段绘制背景

来源:互联网 发布:运营书籍 知乎 编辑:程序博客网 时间:2024/05/16 23:47

MPAndroidChart是Android平台上一款强大易用的图表库,支持线状图、柱状图、散点图等八种图表类型和缩放、拖动(平移)、选择等手势,还支持动画和高亮等功能。但是别人给好的功能毕竟只能满足一般功能,一个程序员最基本的能力就应该是根据需求做出自定义的功能了,这里我对MPAndroidChart进行一些改造,MPAndroidChart只能在节点绘制圆形,现在要给它加上绘制叉号的功能。另外,本来MPAndroidChart的背景只能设置整个一大块背景,现在我加上了按行设置背景色的功能。

效果如图:

节点的细节部分:

功能实现

继承LineChart

自定义LineChart的第一步是要继承LineChart,实现其构造方法。然后重写onDraw方法,在onDraw方法中,再绘制背景,绘制叉号,绘制图表。这里要注意绘制的顺序,从下到上,一层层叠加。

    /**     * 重写onDraw方法,注意绘制顺序,先绘制背景色,再绘制叉号,最后绘制图表     * @param canvas     */    @Override    protected void onDraw(Canvas canvas) {        drawBgColor(canvas);        drawCross(canvas);        super.onDraw(canvas);        Log.i(TAG, "onDraw");    }

画背景

为了让代码看起来更直观,我先创建了一个类BgColor,其中包含start,stop和color三个属性。

/** * Created by xiaoniu on 2017/4/10. * BgColor是设置背景的单位,创建时需要传入起点和终点的值,还有要设置的颜色 * 如要把纵坐标20-40的背景设为红色,就新建一个BgColor * new BgColor(20,40,Color.RED) */public class BgColor {    /**     * @param start 起始点     * @param stop 结束点     * @param color 颜色     */    public BgColor( float start, float stop,int color) {        this.start = stop;        this.stop = start;        this.color = color;    }    private float start;    private float stop;    private int color;    public float getStart() {        return start;    }    public void setStart(float start) {        this.start = start;    }    public float getStop() {        return stop;    }    public void setStop(float stop) {        this.stop = stop;    }    public int getColor() {        return color;    }    public void setColor(int color) {        this.color = color;    }}

三个属性分别对应起始点,结束点和颜色。然后将自己需要设置的背景都放到一个List中。

    /**     * 分段背景设置     * @return 每条背景的组合     */    private ArrayList<BgColor> getBg() {        ArrayList<BgColor> bgList = new ArrayList<>();        bgList.add(new BgColor(10, 20, Color.YELLOW));//参数信息:纵坐标从0到20设置颜色为黄色        bgList.add(new BgColor(20, 40, 0xFF00FF00));//支持16进制颜色        bgList.add(new BgColor(40, 70, Color.BLUE));        bgList.add(new BgColor(70, 80, Color.RED));        return bgList;    }

别忘了给图表设置绘制背景的属性,之后再把数据传给图表。

//给表格背景添加颜色mChart.setDrawBgColor(true);//设置背景颜色的属性mChart.setBgColor(getBg());

而在自定义LineChart的drawBgColor方法中,就是从List中取出每个BgColor,获得其start和stop,再根据MPAndroidChart提供的能够将图表上的值转换为像素坐标点的方法getPixelForValues,得到需要绘制背景的左下角和右上角的坐标,用canvas画矩形就可以了。

private void drawBgColor(Canvas canvas) {        if (enableDrawBgColor) {            if (!bgList.isEmpty()) {                Paint paint = new Paint();                for (BgColor r : bgList                        ) {                    MPPointD pStart = this.getPixelForValues(this.getXChartMin(), r.getStart(), YAxis.AxisDependency.LEFT);//左下角                    MPPointD pStop = this.getPixelForValues(this.getXChartMax(), r.getStop(), YAxis.AxisDependency.LEFT);//右上角                    paint.setColor(r.getColor());                    canvas.drawRect(new RectF((float) pStart.x, (float) pStart.y, (float) pStop.x, (float) pStop.y), paint);                }            }else {                Log.i(TAG, "No BgColor to Draw");            }        }    }

画叉号

画叉号之前要得到节点的数据,同样是利用getPixelForValues将图表上的值转化为像素坐标点

private void drawCross(Canvas canvas) {        if (enableDrawCross) {            if (this.getData() != null) {                LineDataSet set = (LineDataSet) this.getData().getDataSetByIndex(0);                list = set.getValues();                set.setDrawCircles(false);                LineData data = new LineData(set);                this.setData(data);                for (Entry e : list                        ) {                    MPPointD p = this.getPixelForValues(e.getX(), e.getY(), YAxis.AxisDependency.LEFT);                    drawNode(canvas, (float) p.x, (float) p.y);                }            }else{                Log.i(TAG, "No Data to Draw");            }        }    }

画叉号就是绘制两个互相垂直的直线,有了像素坐标点和canvas也就很简单了。

    private void drawNode(Canvas canvas, float x, float y) {        Paint paint = new Paint();        paint.setColor(Color.RED);        paint.setStrokeWidth(crossWidth);        canvas.drawLine(x - crossLength / 2, y - crossLength / 2, x + crossLength / 2, y + crossLength / 2, paint);        canvas.drawLine(x - crossLength / 2, y + crossLength / 2, x + crossLength / 2, y - crossLength / 2, paint);    }

END

细节比较粗糙,以后再完善,欢迎评论交流。

最后附上github代码:https://github.com/xiaoniu/CrossNodeLineChart

原创粉丝点击