使用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功能真的很強大,之前一直想要自己來畫曲線圖,浪費了幾天功夫。所以說,站在巨人的肩膀上是很重要的。對於程序員,有一句很重要的話,叫做不要重復造輪子。但是,要使用別人的輪子,必須先要理解透徹,否則很難實現漂亮的效果。

由於筆者水平有限,如有錯漏之處在所難免,歡迎讀者批評指正,感激不盡!

原創文章,轉載請注明出處。

 

全文完

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM