当前位置:   article > 正文

Android开源图表库:HelloCharts_com.github.lecho:hellocharts-android

com.github.lecho:hellocharts-android

Github-hellocharts

探讨向

使用方式

  • 导入库
build.gradle中加入compile 'com.github.lecho:hellocharts-library:1.5.8@aar'


  • 简单折线图的使用方式

布局
在布局文件中加入
<lecho.lib.hellocharts.view.LineChartView
android: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中:

  1. PointValue p1 = new PointValue(1, 4);
  2. PointValue p2 = new PointValue(2, 3);
  3. PointValue p3 = new PointValue(3, 5);
  4. List<PointValue> pointValueList = new ArrayList<>();
  5. pointValueList.add(p1);
  6. pointValueList.add(p2);
  7. pointValueList.add(p3);

好了,现在3个点已经构建完毕。整理一下代码:

  1. void initChart() {
  2. // 创建3个坐标点
  3. PointValue p1 = new PointValue(1, 4);
  4. PointValue p2 = new PointValue(2, 3);
  5. PointValue p3 = new PointValue(3, 5);
  6. List<PointValue> pointValueList = new ArrayList<>();
  7. pointValueList.add(p1);
  8. pointValueList.add(p2);
  9. pointValueList.add(p3);
  10. // 通过坐标点创建出一根折线
  11. Line line = new Line(pointValueList);
  12. List<Line> lines = new ArrayList<>();
  13. lines.add(line);
  14. // 创建LineChartData对象,并通过setLines方法将只包含了一根折线的列表传入
  15. LineChartData data = new LineChartData();
  16. data.setLines(lines);
  17. // 实例化LineChartView,并传入数据data
  18. LineChartView lineChartView = (LineChartView) findViewById(R.id.line_chart_view);
  19. lineChartView.setLineChartData(data);
  20. }

最后在onCreate方法中调用initChart()方法进行初始化,看看效果:



发现,只有折线,少了坐标轴啊!那么继续,建立坐标轴:
在HelloCharts中,坐标轴是用Axis对象表示的。
在lineChartView.setLineChartData(data)语句之前,先创建两个Axis对象,axisX和axisY,分别表示X轴和Y轴。然后将其加入到data中。在data中,横纵坐标均有两种添加方式可以选择,分别代表横坐标位于上或下,以及纵坐标位于左或右。这里选择纵坐标在左边,横坐标在下方。

  1. // 创建坐标轴
  2. Axis axisX = new Axis();
  3. Axis axisY = new Axis();
  4. // 将坐标轴传入到data中
  5. data.setAxisXBottom(axisX);
  6. data.setAxisYLeft(axisY);

再看看效果:



可以看到,一个折线图已经基本完成了!最后再设置一下坐标的属性:

  1. axisX.setTextColor(Color.BLACK);
  2. axisX.setName("横坐标");
  3. axisY.setTextColor(Color.BLACK);
  4. axisY.setName("纵坐标");

最终效果:

  1. void initChart() {
  2. // 创建3个坐标点
  3. PointValue p1 = new PointValue(1, 4);
  4. PointValue p2 = new PointValue(2, 3);
  5. PointValue p3 = new PointValue(3, 5);
  6. List<PointValue> pointValueList = new ArrayList<>();
  7. pointValueList.add(p1);
  8. pointValueList.add(p2);
  9. pointValueList.add(p3);
  10. // 通过坐标点创建出一根折线
  11. Line line = new Line(pointValueList);
  12. line.setColor(Color.BLACK);
  13. List<Line> lines = new ArrayList<>();
  14. lines.add(line);
  15. // 创建LineChartData对象,并通过setLines方法将只包含了一根折线的列表传入
  16. LineChartData data = new LineChartData();
  17. data.setLines(lines);
  18. // 创建坐标轴
  19. Axis axisX = new Axis();
  20. Axis axisY = new Axis();
  21. axisX.setTextColor(Color.BLACK);
  22. axisX.setName("横坐标");
  23. axisY.setTextColor(Color.BLACK);
  24. axisY.setName("纵坐标");
  25. // 将坐标轴传入到data中
  26. data.setAxisXBottom(axisX);
  27. data.setAxisYLeft(axisY);
  28. // 实例化LineChartView,并传入数据data
  29. LineChartView lineChartView = (LineChartView) findViewById(R.id.line_chart_view);
  30. lineChartView.setLineChartData(data);
  31. }






  • 进阶设置:坐标轴和Viewport
在使用的过程中我发现,如果数据过多,折线会全部在屏幕上挤成一团,非常不美观,需要放大之后才能看清楚。
比如我要做一个x轴为日期,y轴为访问量的图表,一共150个数据,代码和结果如下所示:

  1. void buildChartTotal() {
  2. List<String> dateList = new ArrayList<>();
  3. List<Integer> visitorNumList = new ArrayList<>();
  4. for (String[] strs : dailyDataSplit) {
  5. String sDate = strs[1] + "/" + strs[2];
  6. int sVisitorNum = Integer.parseInt(strs[3]);
  7. if (!dateList.contains(sDate)) {
  8. dateList.add(sDate);
  9. visitorNumList.add(sVisitorNum);
  10. }
  11. }
  12. List<AxisValue> axisXValueList = new ArrayList<>();
  13. List<PointValue> pointValueList = new ArrayList<>();
  14. for (int i = 0; i < dateList.size(); i++) {
  15. axisXValueList.add(new AxisValue(i).setLabel(dateList.get(i)));
  16. pointValueList.add(new PointValue(i, visitorNumList.get(i)));
  17. }
  18. Axis axisX = new Axis(axisXValueList);
  19. axisX.setTextColor(R.color.dark_gray);
  20. axisX.setName("日期");
  21. axisX.setHasLines(true);
  22. Axis axisY = new Axis();
  23. axisY.setValues(axisYValueList);
  24. axisY.setTextColor(R.color.dark_gray);
  25. axisY.setName("访问总人数");
  26. Line line = new Line(pointValueList);
  27. line.setColor(R.color.dark_gray);
  28. line.setHasLabels(true);
  29. List<Line> lines = new ArrayList<>();
  30. lines.add(line);
  31. LineChartData lineChartData = new LineChartData(lines);
  32. lineChartData.setAxisXBottom(axisX);
  33. lineChartData.setAxisYLeft(axisY);
  34. lineChartView.setZoomType(ZoomType.HORIZONTAL);
  35. lineChartView.setInteractive(true);
  36. lineChartView.setLineChartData(lineChartData);
  37. }






显然,这样的显示效果并不好。考虑到以下问题:
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轴标签的密度了,非常简单。


  1. /**
  2. * 最终代码:创建图表
  3. */
  4. void buildChartTotal() {
  5. // 初始化数据列表
  6. List<String> dateList = new ArrayList<>();
  7. List<Integer> visitorNumList = new ArrayList<>();
  8. for (String[] strs : dailyDataSplit) {
  9. String sDate = strs[1] + "/" + strs[2];
  10. int sVisitorNum = Integer.parseInt(strs[3]);
  11. if (!dateList.contains(sDate)) {
  12. dateList.add(sDate);
  13. visitorNumList.add(sVisitorNum);
  14. }
  15. }
  16. List<AxisValue> axisXValueList = new ArrayList<>();
  17. List<AxisValue> axisYValueList = new ArrayList<>();
  18. List<PointValue> pointValueList = new ArrayList<>();
  19. for (int i = 0; i < dateList.size(); i++) {
  20. axisXValueList.add(new AxisValue(i).setLabel(dateList.get(i)));
  21. pointValueList.add(new PointValue(i, visitorNumList.get(i)));
  22. }
  23. // 设置y轴的标签
  24. axisYValueList = createYValue(visitorNumList);
  25. // 设置坐标轴属性
  26. Axis axisX = new Axis(axisXValueList);
  27. axisX.setTextColor(R.color.dark_gray);
  28. axisX.setName("日期");
  29. axisX.setHasLines(true);
  30. Axis axisY = new Axis();
  31. axisY.setValues(axisYValueList);
  32. axisY.setTextColor(R.color.dark_gray);
  33. axisY.setName("访问总人数");
  34. // 创建折线
  35. final Line line = new Line(pointValueList);
  36. line.setColor(R.color.dark_gray);
  37. line.setHasLabels(true);
  38. List<Line> lines = new ArrayList<>();
  39. lines.add(line);
  40. // 创建图标数据
  41. final LineChartData lineChartData = new LineChartData(lines);
  42. lineChartData.setAxisXBottom(axisX);
  43. lineChartData.setAxisYLeft(axisY);
  44. lineChartView.setZoomType(ZoomType.HORIZONTAL);
  45. lineChartView.setInteractive(true);
  46. lineChartView.setLineChartData(lineChartData);
  47. // 设置viewport
  48. Viewport maxViewport = lineChartView.getMaximumViewport();
  49. maxViewport.bottom = maxViewport.bottom - 5;
  50. maxViewport.top = maxViewport.top + 5;
  51. maxViewport.right = maxViewport.right + 0.2f;// 解决最右边的数据可能显示不完全的问题
  52. Viewport viewport = new Viewport(maxViewport);
  53. viewport.left = maxViewport.right - 7.8f;
  54. lineChartView.setCurrentViewport(viewport);
  55. // 点击显示/隐藏折线上显示的数据
  56. btnSetVisibility.setOnClickListener(new View.OnClickListener() {
  57. @Override
  58. public void onClick(View v) {
  59. if (line.hasLabels()) {
  60. line.setHasPoints(false);
  61. line.setHasLabels(false);
  62. } else {
  63. line.setHasLabels(true);
  64. line.setHasPoints(true);
  65. }
  66. // 刷新显示
  67. lineChartView.setCurrentViewport(lineChartView.getCurrentViewport());
  68. }
  69. });
  70. }
  71. List<AxisValue> createYValue(List<Integer> visitNums) {
  72. int max = visitNums.get(0), min = max;
  73. for (int i : visitNums) {
  74. if (i > max) {
  75. max = i;
  76. } else if (min > i) {
  77. min = i;
  78. }
  79. }
  80. max += 5;
  81. min -= 5;
  82. List<AxisValue> axisValueList = new ArrayList<>();
  83. for (int i = min; i < max; i += (max - min) / 20 + 1) {
  84. axisValueList.add(new AxisValue(i).setLabel(String.valueOf(i)));
  85. }
  86. return axisValueList;
  87. }


显示效果:










声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/254697
推荐阅读
相关标签
  

闽ICP备14008679号