使用AChartEngine画动态曲线图

AChartEngine是一个开源的Android图表库,可以用来画折线图、平滑折线图、饼图、直方图等等。使用简单,功能强大。

AChartEngine官网:http://www.achartengine.org/

AChartEngine库文件:http://repository-achartengine.forge.cloudbees.com/snapshot/org/achartengine/achartengine/1.2.0/

库文件直接导入就可以使用了。

网上介绍AChartEngine的文章很多,不过大多数都只是贴代码,没有讲述相关类及其原理。最新项目要画折线图,搜集了很多资料才弄清楚原理,在此总结整理,希望给读者一个较清晰的理解,少走弯路。由于我的项目中只用到了折线图,在此我只讲解折线图,其他图标原理也是类似的。

AChartEngine官方提供的Demo中,所有的图表都是使用Intent的方式来画的,在实际项目中,这种方式不够灵活,因为一个页面不可能只显示图表,或者不止显示一个图表。

AChartEngine给我们提供了GraphicalView这个类,可以灵活的在任何位置插入图表,非常的方便。

下面对相关类进行讲解:

GraphicalView:图表控件,是一个基本类,也是一个容器控件,所有的图表都在此控件中呈现;

ChartFactory:工厂类,通过此类来构建不同的图表对象,比如LineChart(折线图)、CubeLineChart(圆滑折线图)、PieChart(饼图)等;

XYMultipleSeriesDataset:数据集容器,在此类中存放多条曲线的数据集合
XYMultipleSeriesRenderer:渲染器容器,此类初始化坐标系,网格,标题等,还用来存放多条曲线的渲染器
XYSeries:数据集,存放曲线的数据
XYSeriesRenderer:渲染器,存放曲线的参数,比如线条颜色,描点大小等

以下以一个简单的动态折线图来展现相关类的调用,其中ChartService是我自己定义的一个类,可以直接使用到实际项目中:

效果图

MainActivity:

 1 package com.example.mychartdemo;
 2
 3 import java.util.Timer;
 4 import java.util.TimerTask;
 5
 6 import org.achartengine.GraphicalView;
 7
 8 import com.ivan.chart.ChartService;
 9
10 import android.app.Activity;
11 import android.graphics.Color;
12 import android.os.Bundle;
13 import android.os.Handler;
14 import android.os.Message;
15 import android.view.Menu;
16 import android.view.ViewGroup.LayoutParams;
17 import android.widget.LinearLayout;
18
19 public class MainActivity extends Activity {
20
21     private LinearLayout mLeftCurveLayout;//存放左图表的布局容器
22     private LinearLayout mRightCurveLayout;//存放右图表的布局容器
23     private GraphicalView mView, mView2;//左右图表
24     private ChartService mService, mService2;
25     private Timer timer;
26
27     @Override
28     protected void onCreate(Bundle savedInstanceState) {
29         super.onCreate(savedInstanceState);
30         setContentView(R.layout.activity_main);
31
32         mLeftCurveLayout = (LinearLayout) findViewById(R.id.left_temperature_curve);
33         mRightCurveLayout = (LinearLayout) findViewById(R.id.right_temperature_curve);
34
35         mService = new ChartService(this);
36         mService.setXYMultipleSeriesDataset("左温度曲线");
37         mService.setXYMultipleSeriesRenderer(100, 100, "左温度曲线", "时间", "温度",
38                 Color.RED, Color.RED, Color.RED, Color.BLACK);
39         mView = mService.getGraphicalView();
40
41         mService2 = new ChartService(this);
42         mService2.setXYMultipleSeriesDataset("右温度曲线");
43         mService2.setXYMultipleSeriesRenderer(100, 100, "右温度曲线", "时间", "温度",
44                 Color.RED, Color.RED, Color.RED, Color.BLACK);
45         mView2 = mService2.getGraphicalView();
46
47         //将左右图表添加到布局容器中
48         mLeftCurveLayout.addView(mView, new LayoutParams(
49                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
50         mRightCurveLayout.addView(mView2, new LayoutParams(
51                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
52
53         timer = new Timer();
54         timer.schedule(new TimerTask() {
55             @Override
56             public void run() {
57                 handler.sendMessage(handler.obtainMessage());
58             }
59         }, 10, 1000);
60     }
61
62     @Override
63     public boolean onCreateOptionsMenu(Menu menu) {
64         getMenuInflater().inflate(R.menu.main, menu);
65         return true;
66     }
67
68     private int t = 0;
69     private Handler handler = new Handler() {
70         @Override
71         //定时更新图表
72         public void handleMessage(Message msg) {
73             mService.updateChart(t, Math.random() * 100);
74             mService2.updateChart(t, Math.random() * 100);
75             t+=5;
76         }
77     };
78
79     @Override
80     protected void onDestroy() {
81         super.onDestroy();
82         if (timer != null) {
83             timer.cancel();
84         }
85     }
86
87 }

ChartService:

  1 package com.ivan.chart;
  2
  3 import java.util.List;
  4
  5 import org.achartengine.ChartFactory;
  6 import org.achartengine.GraphicalView;
  7 import org.achartengine.chart.PointStyle;
  8 import org.achartengine.model.XYMultipleSeriesDataset;
  9 import org.achartengine.model.XYSeries;
 10 import org.achartengine.renderer.XYMultipleSeriesRenderer;
 11 import org.achartengine.renderer.XYSeriesRenderer;
 12 import android.content.Context;
 13 import android.graphics.Color;
 14 import android.graphics.Paint.Align;
 15
 16 public class ChartService {
 17
 18     private GraphicalView mGraphicalView;
 19     private XYMultipleSeriesDataset multipleSeriesDataset;// 数据集容器
 20     private XYMultipleSeriesRenderer multipleSeriesRenderer;// 渲染器容器
 21     private XYSeries mSeries;// 单条曲线数据集
 22     private XYSeriesRenderer mRenderer;// 单条曲线渲染器
 23     private Context context;
 24
 25     public ChartService(Context context) {
 26         this.context = context;
 27     }
 28
 29     /**
 30      * 获取图表
 31      *
 32      * @return
 33      */
 34     public GraphicalView getGraphicalView() {
 35         mGraphicalView = ChartFactory.getCubeLineChartView(context,
 36                 multipleSeriesDataset, multipleSeriesRenderer, 0.1f);
 37         return mGraphicalView;
 38     }
 39
 40     /**
 41      * 获取数据集,及xy坐标的集合
 42      *
 43      * @param curveTitle
 44      */
 45     public void setXYMultipleSeriesDataset(String curveTitle) {
 46         multipleSeriesDataset = new XYMultipleSeriesDataset();
 47         mSeries = new XYSeries(curveTitle);
 48         multipleSeriesDataset.addSeries(mSeries);
 49     }
 50
 51     /**
 52      * 获取渲染器
 53      *
 54      * @param maxX
 55      *            x轴最大值
 56      * @param maxY
 57      *            y轴最大值
 58      * @param chartTitle
 59      *            曲线的标题
 60      * @param xTitle
 61      *            x轴标题
 62      * @param yTitle
 63      *            y轴标题
 64      * @param axeColor
 65      *            坐标轴颜色
 66      * @param labelColor
 67      *            标题颜色
 68      * @param curveColor
 69      *            曲线颜色
 70      * @param gridColor
 71      *            网格颜色
 72      */
 73     public void setXYMultipleSeriesRenderer(double maxX, double maxY,
 74             String chartTitle, String xTitle, String yTitle, int axeColor,
 75             int labelColor, int curveColor, int gridColor) {
 76         multipleSeriesRenderer = new XYMultipleSeriesRenderer();
 77         if (chartTitle != null) {
 78             multipleSeriesRenderer.setChartTitle(chartTitle);
 79         }
 80         multipleSeriesRenderer.setXTitle(xTitle);
 81         multipleSeriesRenderer.setYTitle(yTitle);
 82         multipleSeriesRenderer.setRange(new double[] { 0, maxX, 0, maxY });//xy轴的范围
 83         multipleSeriesRenderer.setLabelsColor(labelColor);
 84         multipleSeriesRenderer.setXLabels(10);
 85         multipleSeriesRenderer.setYLabels(10);
 86         multipleSeriesRenderer.setXLabelsAlign(Align.RIGHT);
 87         multipleSeriesRenderer.setYLabelsAlign(Align.RIGHT);
 88         multipleSeriesRenderer.setAxisTitleTextSize(20);
 89         multipleSeriesRenderer.setChartTitleTextSize(20);
 90         multipleSeriesRenderer.setLabelsTextSize(20);
 91         multipleSeriesRenderer.setLegendTextSize(20);
 92         multipleSeriesRenderer.setPointSize(2f);//曲线描点尺寸
 93         multipleSeriesRenderer.setFitLegend(true);
 94         multipleSeriesRenderer.setMargins(new int[] { 20, 30, 15, 20 });
 95         multipleSeriesRenderer.setShowGrid(true);
 96         multipleSeriesRenderer.setZoomEnabled(true, false);
 97         multipleSeriesRenderer.setAxesColor(axeColor);
 98         multipleSeriesRenderer.setGridColor(gridColor);
 99         multipleSeriesRenderer.setBackgroundColor(Color.WHITE);//背景色
100         multipleSeriesRenderer.setMarginsColor(Color.WHITE);//边距背景色,默认背景色为黑色,这里修改为白色
101         mRenderer = new XYSeriesRenderer();
102         mRenderer.setColor(curveColor);
103         mRenderer.setPointStyle(PointStyle.CIRCLE);//描点风格,可以为圆点,方形点等等
104         multipleSeriesRenderer.addSeriesRenderer(mRenderer);
105     }
106
107     /**
108      * 根据新加的数据,更新曲线,只能运行在主线程
109      *
110      * @param x
111      *            新加点的x坐标
112      * @param y
113      *            新加点的y坐标
114      */
115     public void updateChart(double x, double y) {
116         mSeries.add(x, y);
117         mGraphicalView.repaint();//此处也可以调用invalidate()
118     }
119
120     /**
121      * 添加新的数据,多组,更新曲线,只能运行在主线程
122      * @param xList
123      * @param yList
124      */
125     public void updateChart(List<Double> xList, List<Double> yList) {
126         for (int i = 0; i < xList.size(); i++) {
127             mSeries.add(xList.get(i), yList.get(i));
128         }
129         mGraphicalView.repaint();//此处也可以调用invalidate()
130     }
131 }

布局文件:activity_main:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical"
 6     android:paddingBottom="@dimen/activity_vertical_margin"
 7     android:paddingLeft="@dimen/activity_horizontal_margin"
 8     android:paddingRight="@dimen/activity_horizontal_margin"
 9     android:paddingTop="@dimen/activity_vertical_margin"
10     tools:context=".MainActivity" >
11
12     <LinearLayout
13         android:layout_width="match_parent"
14         android:layout_height="0dp"
15         android:layout_marginBottom="20dp"
16         android:layout_weight="1"
17         android:orientation="vertical" >
18
19         <TextView
20             android:layout_width="wrap_content"
21             android:layout_height="wrap_content"
22             android:layout_marginBottom="10dp"
23             android:text="左温度曲线" />
24
25         <LinearLayout
26             android:id="@+id/left_temperature_curve"
27             android:layout_width="match_parent"
28             android:layout_height="match_parent"
29             android:orientation="horizontal" >
30         </LinearLayout>
31     </LinearLayout>
32
33     <LinearLayout
34         android:layout_width="match_parent"
35         android:layout_height="0dp"
36         android:layout_weight="1"
37         android:orientation="vertical" >
38
39         <TextView
40             android:layout_width="wrap_content"
41             android:layout_height="wrap_content"
42             android:layout_marginBottom="10dp"
43             android:text="右温度曲线" />
44
45         <LinearLayout
46             android:id="@+id/right_temperature_curve"
47             android:layout_width="match_parent"
48             android:layout_height="match_parent"
49             android:orientation="horizontal" >
50         </LinearLayout>
51     </LinearLayout>
52
53 </LinearLayout>

详细说明见注释。

AChartEngine功能真的很强大,之前一直想要自己来画曲线图,浪费了几天功夫。所以说,站在巨人的肩膀上是很重要的。对于程序员,有一句很重要的话,叫做不要重复造轮子。但是,要使用别人的轮子,必须先要理解透彻,否则很难实现漂亮的效果。

由于笔者水平有限,如有错漏之处在所难免,欢迎读者批评指正,感激不尽!

原创文章,转载请注明出处。

全文完

时间: 2024-10-02 20:51:10

使用AChartEngine画动态曲线图的相关文章

achartengine画出动态折线图

achartengine画出动态折线图的效果最近有个项目需要用到实时曲线图,我也上网搜索了一下,最后还是选择使用achartengine这个现成的东西,毕竟自己再canvas一下实在是太麻烦,而且项目时间上也不允许,虽然这个画图引擎比较简单,不过勉强够用了. 下一步问题就来了,我仓促上手,只会画静态图,就是事先定义好几个坐标,然后activity载入的时候折线就已经画好了,可是我的项目要求我每隔一秒种都要把新搜集到的数据添加到图表中去,类似于windows中那个任务管理器里的性能统计图,网上搜来

Excel2010画动态甘特图

哈哈!你居然真的看简介点进来啦,我也想八一八Henry gantt本人的故事,可是我查了好些资料,一个槽点都没有发现,不过人生经历还是可以了解下: 此人活了58年,生前是一个中规中距的机械工程师&项目管理(PM),活在资本主义螺丝钉,发表过几篇不痛不痒关于项目管理方面的论文和书,可是(人生大转折哇) 在55岁那一年,积累了那么多年的经验,终于顿悟,发明了gantt图,并于同一年发表了 Industrial leadership, 再之后,夜以继日(脑补剧情)地工作,终于在58岁那年又发表了一篇p

画动态热图

动态图可以更加清晰的反映某种特征的变化趋势,从而给人直观的感受,帮助人们理解抽象化的特征或者不易直接观察到的特征变化趋势. import numpy as np from matplotlib import pyplot as plt from matplotlib import animation imgData = np.random.random((4368,3,16,16)) fig = plt.figure() data = np.random.random((16, 16)) im

iOS 中各种折线.曲线.图形绘制方法集锦(折线图.走势图.柱状图.动态曲线图.形状图.划线图)

前言 具体实现如下: 目录 前言 第一 折线图实现 .1) 自定义视图实现 .2)关键技术实现 .3) 方法调用 .4) 效果展示 第二 走势曲线图实现 .1) 导入DJChart第三方库 .2)横竖轴参数设置 .3) 方法调用 .4) 效果展示 第三 画线图实现 .1) 导入ZXQuartz第三方库 .2) 自定义视图,画各种图形 .3) 方法调用 .4) 效果展示 第四 柱状图实现 .1) 导入ZXQuartz第三方库 .2)横竖轴参数设置 .3) 方法调用 .4) 效果展示 第五 各式图形

matlab 如何画动态图(绘图与旋转视图)

绘图 效果图: 在matlab中,作图是重要的一部分,那么对于三维的图像,如何将静态的改为动态的呢? 首先,静态图的代码: t=0:0.1:20; i=(1:200); %这里只是画了一个点'*'而已, 因为i取值为1. h=plot3(sin(t(i)),cos(t(i)),t(i),'*','erasemode','none'); grid on % 网格化:即显示坐标轴中的网格,一般三维坐标都要使用 axis([-2 2 -2 2 0 35]) %指三维的坐标轴分别的长度 title('1

Android 用achartengine 画折线图怎么显示不正确

============问题描述============ X.Y的刻度值都是我自己定义的 显示的点的位置不正确 请问是什么原因 怎么处理  还有我设置了显示网格 为什么不显示了 Y轴不设置自己的定义的刻度值 但是刻度个数又不对 这种情况显示是正确的就是刻度个数不够 ============解决方案1============ 属性设置不对,找个demo仔细看看设置,看自己哪里设置不对. ============解决方案2============ 我以前整理的一个曲线图,我共享下,你下载看看,里面东

Android通过achartengine画折线图

因为前段时间Android项目中用到了折线图的功能,在查资料的过程中发现achartengine这个包有非常强大的画图功能,正好最近有时间,就整理一下方便以后查看. 首先要使用画图功能,就必须在lib中引入achartengine包.为了使用方便,直接使用示例中的两个文件,源码如下: IDemoChart.java import android.content.Context; import android.content.Intent; /** * Defines the demo chart

CSS+transform画动态表情

先给大家看下画完后是什么样子: 代码看这里: html代码: <body> <div class="emoji emoji_like"> <div class="emoji_hand"> <div class="emoji_thumb"></div> </div> </div> <div class="emoji emoji_love"&

Android使用Catmull_Rom插值算法画光滑曲线图

一.算法核心思想 1.每次插值需要四个基础点(暂假设为A.B.C.D). 2.根据已知的四个基础点,插值算法每次只能实现在中间两个点间画出光滑的曲线(此处就是B点和C点). 二.工程代码 1."Catmull_Rom插值算法"画光滑曲线的类(Catmull_Rom.java) </pre><pre name="code" class="java">package com.example.test; import java.