【叨、校長】Android報表工具AChartEngine初探總結
AChartEngine是一個安卓系統上製作圖表的框架,目前它支援如下的圖表型別:
•line chart (折線圖)
•area chart (面積圖;分割槽圖,對比圖)
•scatter chart ( 散點圖)
•time chart (時間圖;進度表)
•bar chart (條形圖;柱狀圖)
•pie chart ( 餅圖)
•bubble chart (氣泡圖)
•doughnut chart (圓環圖)
•range (high-low) bar chart (範圍條形圖)
•dial chart / gauge (撥號盤/壓力錶)
•combined (any combination of line, cubic line, scatter, bar, range bar, bubble) chart(組合圖)
•cubic line chart (立方折線圖)
上述所有支援的圖表型別,都可以包含多個系列,都支援水平(預設)或垂直方式展示圖表,並且支援許多其他的自定義功能。所有圖表都可以建立為一個view,也可以建立為一個用於啟動activity的intent.
這個模型和繪圖過程的程式碼進行了很好優化處理,它可以處理和顯示值的數量非常大。
目前為止AchartEngine最新版是1.0.0版本。
以下程式碼基於1.0.0版本:
1.0.0版本相對以前的使用簡單了很多!程式碼也很簡潔!
下面是我整理、摸索出來的使用方法:
折線圖:
首先通過閱讀官方程式碼可以發現有倆個很重要的類:
1、介面IDemoChart:
/** * Copyright (C) 2009, 2010 SC 4ViewSoft SRL * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.achartengine.chartdemo.demo.chart; import android.content.Context; import android.content.Intent; /** * Defines the demo charts. */ public interface IDemoChart { /** A constant for the name field in a list activity. */ String NAME = "name"; /** A constant for the description field in a list activity. */ String DESC = "desc"; /** * Returns the chart name. * * @return the chart name */ String getName(); /** * Returns the chart description. * * @return the chart description */ String getDesc(); /** * Executes the chart demo. * * @param context the context * @return the built intent */ Intent execute(Context context); }
這個介面對實現chart圖示的方法進行了抽象!
我們可以通過實現這個介面的方法來很方便的實現我們想要的Chart
在官方Demo中有一個類對此進行了實現、我們只要經常該類就可以很方便的實現我們自己的chart而不像之前版本那樣的繁瑣!
類AbstractDemoChart:
/**
* Copyright (C) 2009, 2010 SC 4ViewSoft SRL
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.achartengine.chartdemo.demo.chart;
import java.util.Date;
import java.util.List;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.CategorySeries;
import org.achartengine.model.MultipleCategorySeries;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
/**
* An abstract class for the demo charts to extend. It contains some methods for
* building datasets and renderers.
*/
public abstract class AbstractDemoChart implements IDemoChart {
/**
* Builds an XY multiple dataset using the provided values.
*
* @param titles the series titles
* @param xValues the values for the X axis
* @param yValues the values for the Y axis
* @return the XY multiple dataset
*/
protected XYMultipleSeriesDataset buildDataset(String[] titles, List<double[]> xValues,
List<double[]> yValues) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
addXYSeries(dataset, titles, xValues, yValues, 0);
return dataset;
}
public void addXYSeries(XYMultipleSeriesDataset dataset, String[] titles, List<double[]> xValues,
List<double[]> yValues, int scale) {
int length = titles.length;
for (int i = 0; i < length; i++) {
XYSeries series = new XYSeries(titles[i], scale);
double[] xV = xValues.get(i);
double[] yV = yValues.get(i);
int seriesLength = xV.length;
for (int k = 0; k < seriesLength; k++) {
series.add(xV[k], yV[k]);
}
dataset.addSeries(series);
}
}
/**
* Builds an XY multiple series renderer.
*
* @param colors the series rendering colors
* @param styles the series point styles
* @return the XY multiple series renderers
*/
protected XYMultipleSeriesRenderer buildRenderer(int[] colors, PointStyle[] styles) {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
setRenderer(renderer, colors, styles);
return renderer;
}
protected void setRenderer(XYMultipleSeriesRenderer renderer, int[] colors, PointStyle[] styles) {
renderer.setAxisTitleTextSize(16);
renderer.setChartTitleTextSize(20);
renderer.setLabelsTextSize(15);
renderer.setLegendTextSize(15);
renderer.setPointSize(5f);
renderer.setMargins(new int[] { 20, 30, 15, 20 });
int length = colors.length;
for (int i = 0; i < length; i++) {
XYSeriesRenderer r = new XYSeriesRenderer();
r.setColor(colors[i]);
r.setPointStyle(styles[i]);
renderer.addSeriesRenderer(r);
}
}
/**
* Sets a few of the series renderer settings.
*
* @param renderer the renderer to set the properties to
* @param title the chart title
* @param xTitle the title for the X axis
* @param yTitle the title for the Y axis
* @param xMin the minimum value on the X axis
* @param xMax the maximum value on the X axis
* @param yMin the minimum value on the Y axis
* @param yMax the maximum value on the Y axis
* @param axesColor the axes color
* @param labelsColor the labels color
*/
protected void setChartSettings(XYMultipleSeriesRenderer renderer, String title, String xTitle,
String yTitle, double xMin, double xMax, double yMin, double yMax, int axesColor,
int labelsColor) {
renderer.setChartTitle(title);
renderer.setXTitle(xTitle);
renderer.setYTitle(yTitle);
renderer.setXAxisMin(xMin);
renderer.setXAxisMax(xMax);
renderer.setYAxisMin(yMin);
renderer.setYAxisMax(yMax);
renderer.setAxesColor(axesColor);
renderer.setLabelsColor(labelsColor);
}
/**
* Builds an XY multiple time dataset using the provided values.
*
* @param titles the series titles
* @param xValues the values for the X axis
* @param yValues the values for the Y axis
* @return the XY multiple time dataset
*/
protected XYMultipleSeriesDataset buildDateDataset(String[] titles, List<Date[]> xValues,
List<double[]> yValues) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
int length = titles.length;
for (int i = 0; i < length; i++) {
TimeSeries series = new TimeSeries(titles[i]);
Date[] xV = xValues.get(i);
double[] yV = yValues.get(i);
int seriesLength = xV.length;
for (int k = 0; k < seriesLength; k++) {
series.add(xV[k], yV[k]);
}
dataset.addSeries(series);
}
return dataset;
}
/**
* Builds a category series using the provided values.
*
* @param titles the series titles
* @param values the values
* @return the category series
*/
protected CategorySeries buildCategoryDataset(String title, double[] values) {
CategorySeries series = new CategorySeries(title);
int k = 0;
for (double value : values) {
series.add("Project " + ++k, value);
}
return series;
}
/**
* Builds a multiple category series using the provided values.
*
* @param titles the series titles
* @param values the values
* @return the category series
*/
protected MultipleCategorySeries buildMultipleCategoryDataset(String title,
List<String[]> titles, List<double[]> values) {
MultipleCategorySeries series = new MultipleCategorySeries(title);
int k = 0;
for (double[] value : values) {
series.add(2007 + k + "", titles.get(k), value);
k++;
}
return series;
}
/**
* Builds a category renderer to use the provided colors.
*
* @param colors the colors
* @return the category renderer
*/
protected DefaultRenderer buildCategoryRenderer(int[] colors) {
DefaultRenderer renderer = new DefaultRenderer();
renderer.setLabelsTextSize(15);
renderer.setLegendTextSize(15);
renderer.setMargins(new int[] { 20, 30, 15, 0 });
for (int color : colors) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(color);
renderer.addSeriesRenderer(r);
}
return renderer;
}
/**
* Builds a bar multiple series dataset using the provided values.
*
* @param titles the series titles
* @param values the values
* @return the XY multiple bar dataset
*/
protected XYMultipleSeriesDataset buildBarDataset(String[] titles, List<double[]> values) {
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
int length = titles.length;
for (int i = 0; i < length; i++) {
CategorySeries series = new CategorySeries(titles[i]);
double[] v = values.get(i);
int seriesLength = v.length;
for (int k = 0; k < seriesLength; k++) {
series.add(v[k]);
}
dataset.addSeries(series.toXYSeries());
}
return dataset;
}
/**
* Builds a bar multiple series renderer to use the provided colors.
*
* @param colors the series renderers colors
* @return the bar multiple series renderer
*/
protected XYMultipleSeriesRenderer buildBarRenderer(int[] colors) {
XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
renderer.setAxisTitleTextSize(16);
renderer.setChartTitleTextSize(20);
renderer.setLabelsTextSize(15);
renderer.setLegendTextSize(15);
int length = colors.length;
for (int i = 0; i < length; i++) {
SimpleSeriesRenderer r = new SimpleSeriesRenderer();
r.setColor(colors[i]);
renderer.addSeriesRenderer(r);
}
return renderer;
}
}
通過閱讀這個類的原始碼我們可以發現、對Chart實現了封裝!我們只要簡單的繼承該類、重寫以下方法即可實現我們自己的Chart!如下程式碼所示:折線圖的實現:
這是我自己的一個業務Chart實現:
package com.example.shishi;
import java.util.ArrayList;
import java.util.HashMap;
import org.achartengine.ChartFactory;
import org.achartengine.chart.AbstractChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chartdemo.demo.chart.AbstractDemoChart;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import com.example.service.GetSSCDate;
import com.example.service.GetSSCDate.DateStruct;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
public class ShishiTrendChart extends AbstractDemoChart {
private int _type;
private ArrayList<String> _data;
/**
* 構造方法可以實現自定義的初始化工作:如:資料的獲得
* @param type
* @param data
*/
public ShishiTrendChart(int type,ArrayList<String> data) {
this._data =data;
this._type=type;
}
@Override
public String getName() {
return "號碼走勢圖";
}
@Override
public String getDesc() {
return null;
}
@Override
public Intent execute(Context context) {
String[] legends = { "萬", "千", "百", "十", "個" };// 圖例名稱陣列
String[] legend =new String[_type];// 圖例名稱陣列
for(int i=0;i<_type;i++){
legend[i]=legends[4-i];
}
ArrayList<double[]> x = new ArrayList<double[]>();
ArrayList<double[]> y = new ArrayList<double[]>();
int size = _data.size();
for(int j=0;j<legend.length;j++){//有幾條曲線、就有幾個x軸
double[] xValues = new double[100];
for (int i = 0; i < 100; i++) {
xValues[i] = i + 1;
}
x.add(xValues);
}
for (int i = 1; i <= _type; i++) {//有幾條曲線、就有幾個y軸的座標
double[] yValues = new double[100];
for (int j = 0; j < size; j++) {
yValues[j] = getNum(_data.get(j), i);
}
y.add(yValues);
}
int[] color = new int[] { Color.GRAY, Color.GREEN, Color.CYAN,
Color.YELLOW, Color.GREEN };// 設定每條曲線的顏色 預設是5條
int[] colors =new int[_type];// 實際曲線數量
for(int i=0;i<_type;i++){
colors[i]=color[4-i];
}
PointStyle[] style = new PointStyle[] { PointStyle.POINT,
PointStyle.DIAMOND, PointStyle.TRIANGLE, PointStyle.SQUARE,
PointStyle.CIRCLE };//設定預設曲線的點的形狀
PointStyle[] styles =new PointStyle[_type];// 實際曲線
for(int i=0;i<_type;i++){
styles[i]=style[4-i];
}
XYMultipleSeriesRenderer renderer = buildRenderer(colors, styles);//
setChartSettings(renderer, getName(), "期號", "號碼", 0, 100, 0, 9,
Color.GRAY, Color.GRAY);
renderer.setXLabels(10);// 設定x軸顯示10個點,根據setChartSettings的最大值和最小值自動計算點的間隔
renderer.setYLabels(10);// 設定y軸顯示10個點,根據setChartSettings的最大值和最小值自動計算點的間隔
renderer.setShowGrid(true);// 是否顯示網格
renderer.setApplyBackgroundColor(true);
renderer.setBackgroundColor(Color.BLACK);
renderer.setMarginsColor(Color.BLACK);
renderer.setXLabelsAlign(Align.RIGHT);// 刻度線與刻度標註之間的相對位置關係
renderer.setYLabelsAlign(Align.CENTER);// 刻度線與刻度標註之間的相對位置關係
renderer.setZoomButtonsVisible(true);// 是否顯示放大縮小按鈕
renderer.setPanLimits(new double[] { 0, 100, -1, 10 }); // 設定拖動時X軸Y軸允許的最大值最小值.
// renderer.setZoomLimits(new double[] { 0, 100, -10, 20 });// 設定放大縮小時X軸Y軸允許的最大最小值.
Intent intent = ChartFactory.getLineChartIntent(context,
buildDataset(legend, x, y), renderer,
getName());// 構建Intent
return intent;
}
public double getNum(String s, int i) {
s = s.split(",")[5-i];
return Double.parseDouble(s);
}
}
這樣的程式碼是不是比以前版本的實現清晰、簡潔了很多!
以上程式碼根據官方例項得出!所以務必要寫入官方的倆個實現類:public interface IDemoChart,public abstract class AbstractDemoChart implements IDemoChart這倆個類官方原始碼已經給出!複製到自己的專案當中就行!
對於餅圖、柱狀圖就更簡單了!
參考下列程式碼:
餅圖:
package org.achartengine.chartdemo.demo.chart;
import org.achartengine.ChartFactory;
import org.achartengine.renderer.DefaultRenderer;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
public class BudgetPieChart extends AbstractDemoChart {
public String getName() {
return "Budget chart";
}
public String getDesc() {
return "The budget per project for this year (pie chart)";
}
public Intent execute(Context context) {
double[] values = new double[] { 12, 14, 11, 10, 19 };//餅圖分層5塊,每塊代表的數值
int[] colors = new int[] { Color.BLUE, Color.GREEN, Color.MAGENTA, Color.YELLOW, Color.CYAN };//每塊餅圖的顏色
DefaultRenderer renderer = buildCategoryRenderer(colors);
renderer.setZoomButtonsVisible(true);//設定顯示放大縮小按鈕
renderer.setZoomEnabled(true);//設定允許放大縮小.
renderer.setChartTitleTextSize(20);//設定圖表標題的文字大小
return ChartFactory.getPieChartIntent(context, buildCategoryDataset("Project budget", values),
renderer, "Budget");//構建Intent, buildCategoryDataset是呼叫AbstraDemoChart的構建方法.
}
}
柱狀圖:
package org.achartengine.chartdemo.demo.chart;
import java.util.ArrayList;
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.chart.BarChart.Type;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint.Align;
public class SalesStackedBarChart extends AbstractDemoChart {
public String getName() {
return "Sales stacked bar chart";
}
public String getDesc() {
return "The monthly sales for the last 2 years (stacked bar chart)";
}
public Intent execute(Context context) {
String[] titles = new String[] { "2008", "2007" };//圖例
List<double[]> values = new ArrayList<double[]>();
values.add(new double[] { 14230, 12300, 14240, 15244, 15900, 19200, 22030, 21200, 19500, 15500,
12600, 14000 });//第一種柱子的數值
values.add(new double[] { 5230, 7300, 9240, 10540, 7900, 9200, 12030, 11200, 9500, 10500,
11600, 13500 });//第二中柱子的數值
int[] colors = new int[] { Color.BLUE, Color.CYAN };//兩種柱子的顏色
XYMultipleSeriesRenderer renderer = buildBarRenderer(colors);//呼叫AbstractDemoChart中的方法構建renderer.
setChartSettings(renderer, "Monthly sales in the last 2 years", "Month", "Units sold", 0.5,
12.5, 0, 24000, Color.GRAY, Color.LTGRAY);//呼叫AbstractDemoChart中的方法設定renderer的一些屬性.
renderer.getSeriesRendererAt(0).setDisplayChartValues(true);//設定柱子上是否顯示數量值
renderer.getSeriesRendererAt(1).setDisplayChartValues(true);//設定柱子上是否顯示數量值
renderer.setXLabels(12);//X軸的近似座標數
renderer.setYLabels(5);//Y軸的近似座標數
renderer.setXLabelsAlign(Align.LEFT);//刻度線與X軸座標文字左側對齊
renderer.setYLabelsAlign(Align.LEFT);//Y軸與Y軸座標文字左對齊
renderer.setPanEnabled(true, false);//允許左右拖動,但不允許上下拖動.
// renderer.setZoomEnabled(false);
renderer.setZoomRate(1.1f);//放大的倍率
renderer.setBarSpacing(0.5f);//柱子間寬度
return ChartFactory.getBarChartIntent(context, buildBarDataset(titles, values), renderer,
Type.STACKED);//構建Intent, buildBarDataset是呼叫AbstractDemochart中的方法.
}
}
可以發現都是繼承了抽象類AbstractDemoChart而實現的!
很簡單吧!
以下是一些技巧:
如何設定背景色:
renderer.setApplyBackgroundColor(true);//是否可以自定義背景色
renderer.setBackgroundColor(Color.BLACK); //chart內部的背景色
renderer.setMarginsColor(Color.BLACK);//chart邊緣部分的背景色
以上所述由校長整理、研究所得!