首页 > 代码库 > 使用AChartEngine画动态曲线图

使用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     @Override28     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             @Override56             public void run() {57                 handler.sendMessage(handler.obtainMessage());58             }59         }, 10, 1000);60     }61 62     @Override63     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         @Override71         //定时更新图表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     @Override80     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 x111      *            新加点的x坐标112      * @param y113      *            新加点的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 xList123      * @param yList124      */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     <LinearLayout13         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         <TextView20             android:layout_width="wrap_content"21             android:layout_height="wrap_content"22             android:layout_marginBottom="10dp"23             android:text="左温度曲线" />24 25         <LinearLayout26             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     <LinearLayout34         android:layout_width="match_parent"35         android:layout_height="0dp"36         android:layout_weight="1"37         android:orientation="vertical" >38 39         <TextView40             android:layout_width="wrap_content"41             android:layout_height="wrap_content"42             android:layout_marginBottom="10dp"43             android:text="右温度曲线" />44 45         <LinearLayout46             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功能真的很强大,之前一直想要自己来画曲线图,浪费了几天功夫。所以说,站在巨人的肩膀上是很重要的。对于程序员,有一句很重要的话,叫做不要重复造轮子。但是,要使用别人的轮子,必须先要理解透彻,否则很难实现漂亮的效果。

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

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

 

全文完

 

使用AChartEngine画动态曲线图