赞
踩
探讨向
使用方式
布局:在布局文件中加入<lecho.lib.hellocharts.view.LineChartViewandroid:id="@+id/hello_chart_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
创建一个图表:实例化对象:lineChartView = (LineChartView) findViewById(R.id.line_chart_view);
看看lineChartView中,有个setLineChartData(LineChartData)方法。这个LineChartData对象包含了图表的所有数据,通过这个方法就能设置图表中显示的数据了!
那么LineChartData中的数据该如何添加呢?创建一个LineChartData对象data,如图:
可以发现,有两种方式构建data:第一种是直接在data的构造方法中添加一个List<Line>对象;第二种是通过data.setLines(List<Line>)方法设置Lines。Lines就是图表中的折线对象了!先创建一个Line对象line,再创建一个List<Line> 对象lines,并将line添加到这个List中。然后调用data.setLines(lines)设置折线。
构建Line:
Line的构造方法中可以传入一个List<PointValue>的参数,这个PointValue即是一个点的值了!也就是说,创建一个PointValue对象,就是创建了一个坐标点。而将包括了多个点的List传入Line中,就构建了一条折线!这不就是和手绘折线图的过程一样吗?好,那么创建几个坐标点:
可以看到,PointValue构造方法中有一个PoindValue(float x, float y),参数即是这个点的横纵坐标。创建3个点,并添加到pointValueList中:
PointValue p1 = new PointValue(1, 4); PointValue p2 = new PointValue(2, 3); PointValue p3 = new PointValue(3, 5); List<PointValue> pointValueList = new ArrayList<>(); pointValueList.add(p1); pointValueList.add(p2); pointValueList.add(p3);
好了,现在3个点已经构建完毕。整理一下代码:
void initChart() { // 创建3个坐标点 PointValue p1 = new PointValue(1, 4); PointValue p2 = new PointValue(2, 3); PointValue p3 = new PointValue(3, 5); List<PointValue> pointValueList = new ArrayList<>(); pointValueList.add(p1); pointValueList.add(p2); pointValueList.add(p3); // 通过坐标点创建出一根折线 Line line = new Line(pointValueList); List<Line> lines = new ArrayList<>(); lines.add(line); // 创建LineChartData对象,并通过setLines方法将只包含了一根折线的列表传入 LineChartData data = new LineChartData(); data.setLines(lines); // 实例化LineChartView,并传入数据data LineChartView lineChartView = (LineChartView) findViewById(R.id.line_chart_view); lineChartView.setLineChartData(data); }
最后在onCreate方法中调用initChart()方法进行初始化,看看效果:
发现,只有折线,少了坐标轴啊!那么继续,建立坐标轴:在HelloCharts中,坐标轴是用Axis对象表示的。在lineChartView.setLineChartData(data)语句之前,先创建两个Axis对象,axisX和axisY,分别表示X轴和Y轴。然后将其加入到data中。在data中,横纵坐标均有两种添加方式可以选择,分别代表横坐标位于上或下,以及纵坐标位于左或右。这里选择纵坐标在左边,横坐标在下方。
// 创建坐标轴 Axis axisX = new Axis(); Axis axisY = new Axis(); // 将坐标轴传入到data中 data.setAxisXBottom(axisX); data.setAxisYLeft(axisY);
再看看效果:
可以看到,一个折线图已经基本完成了!最后再设置一下坐标的属性:
axisX.setTextColor(Color.BLACK); axisX.setName("横坐标"); axisY.setTextColor(Color.BLACK); axisY.setName("纵坐标");
最终效果:
void initChart() { // 创建3个坐标点 PointValue p1 = new PointValue(1, 4); PointValue p2 = new PointValue(2, 3); PointValue p3 = new PointValue(3, 5); List<PointValue> pointValueList = new ArrayList<>(); pointValueList.add(p1); pointValueList.add(p2); pointValueList.add(p3); // 通过坐标点创建出一根折线 Line line = new Line(pointValueList); line.setColor(Color.BLACK); List<Line> lines = new ArrayList<>(); lines.add(line); // 创建LineChartData对象,并通过setLines方法将只包含了一根折线的列表传入 LineChartData data = new LineChartData(); data.setLines(lines); // 创建坐标轴 Axis axisX = new Axis(); Axis axisY = new Axis(); axisX.setTextColor(Color.BLACK); axisX.setName("横坐标"); axisY.setTextColor(Color.BLACK); axisY.setName("纵坐标"); // 将坐标轴传入到data中 data.setAxisXBottom(axisX); data.setAxisYLeft(axisY); // 实例化LineChartView,并传入数据data LineChartView lineChartView = (LineChartView) findViewById(R.id.line_chart_view); lineChartView.setLineChartData(data); }
在使用的过程中我发现,如果数据过多,折线会全部在屏幕上挤成一团,非常不美观,需要放大之后才能看清楚。比如我要做一个x轴为日期,y轴为访问量的图表,一共150个数据,代码和结果如下所示:
void buildChartTotal() { List<String> dateList = new ArrayList<>(); List<Integer> visitorNumList = new ArrayList<>(); for (String[] strs : dailyDataSplit) { String sDate = strs[1] + "/" + strs[2]; int sVisitorNum = Integer.parseInt(strs[3]); if (!dateList.contains(sDate)) { dateList.add(sDate); visitorNumList.add(sVisitorNum); } } List<AxisValue> axisXValueList = new ArrayList<>(); List<PointValue> pointValueList = new ArrayList<>(); for (int i = 0; i < dateList.size(); i++) { axisXValueList.add(new AxisValue(i).setLabel(dateList.get(i))); pointValueList.add(new PointValue(i, visitorNumList.get(i))); } Axis axisX = new Axis(axisXValueList); axisX.setTextColor(R.color.dark_gray); axisX.setName("日期"); axisX.setHasLines(true); Axis axisY = new Axis(); axisY.setValues(axisYValueList); axisY.setTextColor(R.color.dark_gray); axisY.setName("访问总人数"); Line line = new Line(pointValueList); line.setColor(R.color.dark_gray); line.setHasLabels(true); List<Line> lines = new ArrayList<>(); lines.add(line); LineChartData lineChartData = new LineChartData(lines); lineChartData.setAxisXBottom(axisX); lineChartData.setAxisYLeft(axisY); lineChartView.setZoomType(ZoomType.HORIZONTAL); lineChartView.setInteractive(true); lineChartView.setLineChartData(lineChartData); }
显然,这样的显示效果并不好。考虑到以下问题:1. 同时显示的数据太多以至于产生重叠;2. 坐标轴上面也不需要这么多的标签;3. 折线的最底部抵在了x轴上面,顶部顶在图表的最上方,我希望上下有一些空白的空间。
所以,这时候需要设置图表中显示的数据范围,减少坐标轴上Label的个数。具体的做法是使用Viewport:
先看看Viewport的说明:
一个Viewport对象包含了4个公开的float类型成员:top,bottom,left,right;通过这4个变量可以设定出该Viewport的上下左右边界。
在lineChartView中有以下4个方法:
getCurrentViewport():获取当前图表的Viewport。
setCurrentViewport(Viewport):设置当前图表的Viewport。即是设置图表的可见部分的边界。
getMaximumViewport():设置图表的最大Viewport。
setMaximumViewport(Viewport):设置图表的最大Viewport。即是设置图表在缩放之后可达到的最外层边界,使用setCurrentViewport也无法超过该范围。
通过使用Viewport来设定显示范围。
1. 在lineChartView.setLineChartData(lineChartData)这条语句之后,通过:
Viewport maxViewport = lineChartView.getMaximumViewport(); 来得到maxViewport。
2. 新建一个Viewport对象:Viewport viewport = new Viewport();3. 对viewport的上下左右4个成员进行赋值。注意这个viewport的边界是 不能超过maxViewport的,而因为希望上下有空白空间,所以竖直方向需要增加高度,所以要先改变maxViewport的top和bottom,让最外层的高度增加:maxViewport.bottom = maxViewport.bottom - 5;
maxViewport.top = maxViewport.top + 5;
然后对viewport的上下边界赋值:viewport.top = maxViewport.top;viewport.bottom = maxViewport.bottom;接下来,假设当前图表要显示最新的8个数据,那么:
viewport.right = maxViewport.right;
viewport.left = maxViewport.right - 7;
这样要想要的viewport就设定好了。最后再调用:
lineChartView.setCurrentViewport(viewport);
就设置好了当前图表显示内容了。
设置Y轴Label的个数
因为Axis的实例中有一个setValues(List<AxisValue> values)方法可以设置坐标轴上标记的值,而只要屏幕显示的下,这个values的size就是坐标轴标签的个数。于是通过这个方法就可以减少y轴标签的密度了,非常简单。
/** * 最终代码:创建图表 */ void buildChartTotal() { // 初始化数据列表 List<String> dateList = new ArrayList<>(); List<Integer> visitorNumList = new ArrayList<>(); for (String[] strs : dailyDataSplit) { String sDate = strs[1] + "/" + strs[2]; int sVisitorNum = Integer.parseInt(strs[3]); if (!dateList.contains(sDate)) { dateList.add(sDate); visitorNumList.add(sVisitorNum); } } List<AxisValue> axisXValueList = new ArrayList<>(); List<AxisValue> axisYValueList = new ArrayList<>(); List<PointValue> pointValueList = new ArrayList<>(); for (int i = 0; i < dateList.size(); i++) { axisXValueList.add(new AxisValue(i).setLabel(dateList.get(i))); pointValueList.add(new PointValue(i, visitorNumList.get(i))); } // 设置y轴的标签 axisYValueList = createYValue(visitorNumList); // 设置坐标轴属性 Axis axisX = new Axis(axisXValueList); axisX.setTextColor(R.color.dark_gray); axisX.setName("日期"); axisX.setHasLines(true); Axis axisY = new Axis(); axisY.setValues(axisYValueList); axisY.setTextColor(R.color.dark_gray); axisY.setName("访问总人数"); // 创建折线 final Line line = new Line(pointValueList); line.setColor(R.color.dark_gray); line.setHasLabels(true); List<Line> lines = new ArrayList<>(); lines.add(line); // 创建图标数据 final LineChartData lineChartData = new LineChartData(lines); lineChartData.setAxisXBottom(axisX); lineChartData.setAxisYLeft(axisY); lineChartView.setZoomType(ZoomType.HORIZONTAL); lineChartView.setInteractive(true); lineChartView.setLineChartData(lineChartData); // 设置viewport Viewport maxViewport = lineChartView.getMaximumViewport(); maxViewport.bottom = maxViewport.bottom - 5; maxViewport.top = maxViewport.top + 5; maxViewport.right = maxViewport.right + 0.2f;// 解决最右边的数据可能显示不完全的问题 Viewport viewport = new Viewport(maxViewport); viewport.left = maxViewport.right - 7.8f; lineChartView.setCurrentViewport(viewport); // 点击显示/隐藏折线上显示的数据 btnSetVisibility.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (line.hasLabels()) { line.setHasPoints(false); line.setHasLabels(false); } else { line.setHasLabels(true); line.setHasPoints(true); } // 刷新显示 lineChartView.setCurrentViewport(lineChartView.getCurrentViewport()); } }); } List<AxisValue> createYValue(List<Integer> visitNums) { int max = visitNums.get(0), min = max; for (int i : visitNums) { if (i > max) { max = i; } else if (min > i) { min = i; } } max += 5; min -= 5; List<AxisValue> axisValueList = new ArrayList<>(); for (int i = min; i < max; i += (max - min) / 20 + 1) { axisValueList.add(new AxisValue(i).setLabel(String.valueOf(i))); } return axisValueList; }
显示效果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。