1. 程式人生 > >【叨、校長】Android報表工具AChartEngine初探總結

【叨、校長】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邊緣部分的背景色

 以上所述由校長整理、研究所得!