65.9K
CodeProject 正在变化。 阅读更多。
Home

查看 Android* 应用中的图表和图形数据分析

2014 年 8 月 14 日

CPOL

12分钟阅读

viewsIcon

19521

本文将讨论在典型的企业级 Android* 应用中,使用图表和图形来呈现数据和分析的各种可用选项。

摘要

本文将讨论在典型的企业级 Android* 应用中,使用图表和图形来呈现数据和分析的各种可用选项。我们将探讨选择一个解决方案而非另一个解决方案的各种优缺点,以及在选择图表库或 API 时需要考虑的其他技术因素。最后,我们将详细介绍如何使用流行的 AChartEngine* 库在 Android 中原生添加饼图、折线图和条形图。

目录

摘要
Android 应用的图表选项和注意事项
AChartEngine 概述和用法
一家零售餐饮企业样本应用 – Little Chef。
菜单类别饼图
折线图销售趋势
条形图销售对比
在 Activity 中嵌入多个图表
摘要

Android 应用的图表选项和注意事项

如果您想在应用中呈现任何类型的数据或分析,良好的可视化表示非常重要。它可以极大地提高用户满意度。选择正确的图表或图形类型同样重要。

对于 Android 应用,目前没有标准的平台库来显示图表。根据应用需求,我们可以使用像 Google Charts* 这样的基于 Web 的图表库,但它要求您的应用在线并能够使用 Google Chart API 来显示图表。如果您的应用已经依赖于其他需要网络访问的 Google 服务,Google Chart API 可以是一个不错的选择。Google Charts 的链接如下。
https://developers.google.com/chart/

下面是一个包含多种可用图表类型的综合图库。
https://google-developers.appspot.com/chart/interactive/docs/gallery

如果您熟悉 HTML5,那么还有更多的图表选项。其中一些 HTML5 库可以与您的应用打包,非常适合离线访问。如果您打算开发跨平台应用,这是一个很好的选择。下面的文章介绍了一个这样的库。
https://software.intel.com/en-us/android/articles/develop-html5-chart-applications-for-android-and-win8-devices

在最终确定基于 Web 的甚至离线 HTML5 图表库之前,您可能需要考虑 Android WebView* 的限制,它通常托管这些解决方案。
https://developer.android.com.cn/guide/webapps/webview.html

需要考虑的其他技术因素包括性能、高级图表自定义、对完整 Android API 的访问、自定义用户交互(例如手势)或其他可访问性问题。上述某些库可能缺乏这些功能。低级别的复杂自定义可能只能通过原生 Android 解决方案实现,有时甚至需要直接使用 OpenGL/GPU 编程,具体取决于您的应用需求。

有时,基于 Web 或 HTML5 的解决方案可能无法满足您的应用需求,或者您更希望使用纯粹的 Android 视图和 Activity 来进行本地图表绘制。这可以使您的应用与其他 Android 应用组件紧密集成,无缝地协调、共享、持久化和恢复活动或图表组件之间所需的数据。这也将允许您的应用根据需要执行高级的低级图表或图形自定义。另一个优点是灵活性,可以直接从原生 Android 图表组件访问完整的 Android API。

有几个第三方库可用于在您的 Android 应用中添加图表。AChartEngine 是其中一个库,目前在 Android 开发者中非常受欢迎,因为它具有社区参与度和使用量。
https://code.google.com/p/achartengine/

它正在积极开发中,并支持多种图表类型。在本文中,我们将使用该库来演示如何在您的 Android 应用中添加一些基本图表——饼图、折线图和条形图/柱状图。

AChartEngine 概述和用法

Android API 使我们能够从零开始构建一个功能齐全的图表解决方案。AChartEngine 正是这样做的,并且功能更强大。它是 Android 上流行的原生图表库之一,功能集非常完善。它支持多种图表类型,并允许我们根据需要自定义图表。它甚至提供了缩放控件来配合图表,以及其他标准的图表功能。

AChartEngine 的主站是 https://code.google.com/p/achartengine/

主站引用的以下文章提供了更多详细信息。
http://jaxenter.com/effort-free-graphs-on-android-with-achartengine-46199.html

AChartEngine 有一个方便的工厂类 ChartFactory,它根据需要返回包装在 Android 视图或 Activity 中的图表。然后,这个图表视图可以像任何其他 Android 视图一样嵌入到其他 Activity 中。

AChartEngine 库的安装和使用与其他 Android 库类似。只需下载 jar 文件,然后将其放入项目的 libs 文件夹中。Eclipse* 或 Gradle* 构建将自动编译并构建库。

使用 AChartEngine 库创建图表的过程对于不同类型的图表来说都是简单且一致的。通过遵循以下基本步骤,我们可以创建一个简单的图表:

  1. 创建一个系列数据集和系列渲染器。AChartEngine 具有用于保存数据(例如 XYMultipleSeriesDataset)和渲染器(例如 XYMultipleSeriesRenderer)的通用类。

    对于基本的折线图

    		XYMultipleSeriesDataset mDataset;
    
    			XYMultipleSeriesRenderer mRenderer;
    
    		double[] xvals = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
    
    			double[] yvals = new double[]{25, 45, 50, 65, 80, 84, 96, 106, 123, 118, 134, 121};
    
    		XYSeries series = new XYSeries("Sales Data");
    
    		for (int i = 0; i < 12; i++)
    
    			series.add(xvals[i], yvals[i]);
    
    		XYSeriesRenderer renderer = new XYSeriesRenderer();
    
    		mDataset.addSeries(series);
    
    			mRenderer.addSeriesRenderer(renderer);
    代码片段 1. 创建系列数据集和渲染器 ++
  2. 使用您的图表标题、颜色、点样式和任何其他自定义项配置渲染器。请注意,我们可以在单个渲染器级别(对应于特定数据系列)以及针对整个图表(例如图表标题)进行配置。>
    		renderer.setColor(Color.GREEN);
    
    		renderer.setPointStyle(PointStyle.CIRCLE);
    
    		mRenderer.setChartTitle("Sales Trend Chart");
    代码片段 2. 配置饼图系列渲染器和主渲染器 ++
  3. 使用内置的 ChartFactory 类,通过提供上述配置的多个系列数据集和渲染器,将图表作为视图(或完整的 Activity)获取。请注意,您还需要传入 Android Context(来自您的 Android Activity)。
    		mChartView = ChartFactory.getLineChartView(context, mDataset, mRenderer);
    代码片段 3. 使用 ChartFactory ++
  4. 在您的 Android Activity 布局 xml 中创建一个布局来容纳图表,例如 LinearLayout,然后将视图添加到布局中。
    		layout = (LinearLayout) findViewById(R.id.chart);
    
    		layout.addView(mChartView);
    代码片段 4. 将图表添加到 Android 布局 ++

现在,我们已经将一个基本的折线图嵌入到了 Android Activity 的线性布局中。

一家零售餐饮企业样本应用 – Little Chef。

为了演示图表的使用,我们使用了一个名为 Little Chef 的餐厅应用。

该应用程序允许用户浏览不同的菜单类别和选项。

图 1. 餐厅样本应用 - Little Chef

这家餐厅的应用可以供厨师或老板使用,他们可以通过饼图查看不同的菜单类别和选项,或者通过折线图查看销售趋势,或者通过条形图/柱状图查看销售对比。以下屏幕截图显示了图表视图。

图 2. 使用 AChartEngine 库显示图表的餐厅样本应用

在样本应用中,餐厅老板可以从主屏幕导航到图表视图。多个图表可以嵌入在同一个 Android Activity 中,或者根据需要每个图表放在一个单独的 Activity 中。

菜单类别饼图

为了演示饼图的使用,我们将以饼图的形式展示不同的菜单类别以及每个类别中的项目数量。
首先,在 Android 布局中为图表定义一个占位符。我们可以选择性地添加一个标题标签,如下面的代码片段所示。

<TextView

	android:layout_width="261dp"

	android:layout_height="104dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Menu Items Pie Chart"

	android:gravity="center"

	android:id="@+id/textView" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart1"

	android:layout_gravity="center_horizontal"

	android:background="@android:color/transparent"></LinearLayout>
代码片段 5. 样本应用的饼图布局 ++

我们使用 ID “chart1” 作为线性布局的引用,该布局托管我们的饼图。

要绘制饼图,我们需要使用 RoundChart。 “圆形”图表的基础知识与 XYChart 类似,除了某些配置和设置。
如 AChartEngine 用法部分所述,我们首先需要定义和初始化我们的数据系列和渲染器。对于饼图,我们分别使用 CategorySeriesDefaultRenderer 类。请参考以下代码片段。

int[] COLORS = new int[]{Color.GREEN, Color.BLUE, Color.MAGENTA, Color.CYAN};

	CategorySeries mSeries = new CategorySeries("");

	DefaultRenderer mRenderer = new DefaultRenderer();

Map<String, Integer> mcount = new HashMap<String, Integer>();

	for (MenuFactory.MenuItem m : menuItems) {

	if (!mcount.containsKey(m.category)) mcount.put(m.category, 1);

	else mcount.put(m.category, mcount.get(m.category) + 1);

	}

for (Map.Entry<String, Integer> m : mcount.entrySet()) {

	mSeries.add(m.getKey(), m.getValue());

	SimpleSeriesRenderer renderer = new SimpleSeriesRenderer();

	renderer.setColor(COLORS[(mSeries.getItemCount() - 1) % COLORS.length]);

	mRenderer.addSeriesRenderer(renderer);

	}

mRenderer.setChartTitle("Menu Item Categories");

	mRenderer.setLabelsColor(Color.BLACK);
代码片段 6. 样本应用的饼图数据初始化 ++

如上面的代码片段所示,使用 SimpleSeriesRenderer 来渲染每个单独的饼图数据。我们在该渲染器上配置每个饼图组件的颜色。所有单独的渲染器都添加到我们的主渲染器对象中。在主渲染器对象上,我们配置图表标题和标签的颜色。

使用 ChartFactory 类,通过传入上下文、数据集和渲染器对象,将饼图作为 Android 视图获取。

mChartView = ChartFactory.getPieChartView(context, mSeries, mRenderer);

LinearLayout layout = (LinearLayout) findViewById(R.id.chart1);

layout.addView(mChartView);
代码片段 7. 在样本应用的 Android 布局中添加饼图 ++

最后,如代码片段所示,饼图可以嵌入到 chart1 线性布局中。
生成的图表显示在以下屏幕截图中。

图 3. 菜单类别饼图

使用折线图显示销售趋势

在餐厅样本应用中,我们可以显示过去一年的销售趋势,并用折线图表示。

在 Android 布局中为图表定义一个占位符。我们使用线性布局,并为其分配一个 ID(例如 chart2)。

<TextView

	android:layout_width="268dp"

	android:layout_height="104dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Sales Trend"

	android:gravity="center"

	android:id="@+id/textView2" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart2"

	android:layout_gravity="center_horizontal"></LinearLayout>
代码片段 8. 样本应用的折线图布局 ++

要绘制饼图,我们需要使用 RoundChart。 “圆形”图表的基础知识与 XYChart 类似,除了某些配置和设置。

定义和初始化我们的数据系列和渲染器。对于折线图,我们分别使用 XYMultipleSeriesDatasetXYMultipleSeriesRenderer 类。请参考以下代码片段。

XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();

	XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();

double[] xvals = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

	double[] yvals = new double[]{25, 45, 50, 65, 80, 84, 96, 106, 123, 118, 134, 121};

XYSeries series = new XYSeries("Sales Data");

	for (int i = 0; i < 12; i++)

	series.add(xvals[i], yvals[i]);

	XYSeriesRenderer renderer = new XYSeriesRenderer();

	renderer.setColor(Color.GREEN);

	renderer.setPointStyle(PointStyle.CIRCLE);

	renderer.setFillPoints(true);

	renderer.setDisplayChartValues(true);

mDataset.addSeries(series);

	mRenderer.addSeriesRenderer(renderer);

mRenderer.setChartTitle("Sales Trend Chart");

	mRenderer.setXTitle("Month");

	mRenderer.setYTitle("Sales in 1000s");

	mRenderer.setXAxisMin(0.5);

	mRenderer.setXAxisMax(12.5);

	mRenderer.setYAxisMin(20);

	mRenderer.setYAxisMax(140);

	mRenderer.setAxesColor(Color.GRAY);

	mRenderer.setLabelsColor(Color.LTGRAY);

	mRenderer.setXLabels(1);

	mRenderer.setYLabels(10);

	mRenderer.addXTextLabel(1, "Jan");

	mRenderer.addXTextLabel(3, "Mar");

	mRenderer.addXTextLabel(5, "May");

	mRenderer.addXTextLabel(7, "Jul");

	mRenderer.addXTextLabel(10, "Oct");

	mRenderer.addXTextLabel(12, "Dec");
代码片段 9. 样本应用的折线图数据集和渲染器设置 ++

此示例使用了样本销售数据,但应用可以请求抽象的后端数据库或模型来返回销售数据。此代码片段显示了我们可以添加到折线图中的其他自定义项。我们添加了月份的文本标签,并配置了颜色和标题等。请参考代码片段了解所有自定义项。

使用 ChartFactory 类,通过传入上下文、数据集和渲染器对象,将折线图作为 Android 视图获取。

mChartView = ChartFactory.getLineChartView(context, mDataset, mRenderer);

LinearLayout layout = (LinearLayout) findViewById(R.id.chart2);

layout.addView(mChartView);
代码片段 10. 在样本应用的 Android 布局中添加折线图 ++

最后,如代码片段所示,饼图可以嵌入到 chart2 线性布局中。

生成的图表显示在以下屏幕截图中。

图 4. 使用折线图显示销售趋势

使用条形图进行销售对比

AChartEngine 允许我们添加任意数量的数据系列。此外,我们可以通过配置相应的渲染器来定制每个数据系列的外观。

添加条形图的过程与前面的图表类似。我们将绘制两年的销售数据进行比较。

与之前一样,在 Android 布局中为图表定义一个占位符。我们使用线性布局,并分配一个 ID(例如 chart3)。

<TextView

	android:layout_width="344dp"

	android:layout_height="122dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Sales Comparison Chart"

	android:gravity="center"

	android:id="@+id/textView3" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart3"

	android:layout_gravity="center_horizontal"></LinearLayout>
代码片段 11. 样本应用的条形图布局 ++

定义和初始化我们的数据系列和渲染器。与折线图类似,对于条形图,我们分别使用 XYMultipleSeriesDatasetXYMultipleSeriesRenderer 类。请参考以下代码片段。

 XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();

	XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();

 

double[] xvals = new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

	double[] yvals = new double[]{25, 45, 50, 65, 80, 84, 96, 106, 123, 118, 134, 121};

	double[] yvals2 = new double[]{35, 55, 40, 75, 65, 90, 106, 100, 130, 125, 144, 131};

XYSeries series = new XYSeries("2012 Sales Data");

	for (int i = 0; i < 12; i++)

	series.add(xvals[i], yvals[i]);

	XYSeriesRenderer renderer = new XYSeriesRenderer();

	renderer.setDisplayChartValues(true);

mDataset.addSeries(series);

	mRenderer.addSeriesRenderer(renderer);

series = new XYSeries("2013 Sales Data");

	for (int i = 0; i < 12; i++)

	series.add(xvals[i], yvals2[i]);

	renderer = new XYSeriesRenderer();

	renderer.setColor(Color.GREEN);

	renderer.setDisplayChartValues(true);

mDataset.addSeries(series);

	mRenderer.addSeriesRenderer(renderer);

mRenderer.setChartTitle("Sales Chart Comparison 2012 - 2013");

	mRenderer.setXTitle("Month");

	mRenderer.setYTitle("Sales in 1000s");

	mRenderer.setXAxisMin(0.5);

	mRenderer.setXAxisMax(12.5);

	mRenderer.setYAxisMin(20);

	mRenderer.setYAxisMax(140);

	mRenderer.setAxesColor(Color.GRAY);

	mRenderer.setLabelsColor(Color.LTGRAY);

	mRenderer.setXLabels(1);

	mRenderer.setYLabels(10);

	mRenderer.addXTextLabel(1, "Jan");

	mRenderer.addXTextLabel(3, "Mar");

	mRenderer.addXTextLabel(5, "May");

	mRenderer.addXTextLabel(7, "Jul");

	mRenderer.addXTextLabel(10, "Oct");

	mRenderer.addXTextLabel(12, "Dec");
代码片段 12. 为样本应用的条形图配置数据集和渲染器 ++

我们可以分别创建和配置每个系列,如代码片段所示。与上一节中的折线图类似,选择了额外的自定义项。由于折线图和条形图都属于同一基本类型的 XYChart,因此有许多相似之处。对于这些类型的图表,从一种类型切换到另一种类型只需更改对 ChartFactory 的调用。

使用 ChartFactory 类,通过传入上下文、数据集和渲染器对象,将条形图作为 Android 视图获取。

mChartView = ChartFactory.getBarChartView(context, mDataset, mRenderer, BarChart.Type.DEFAULT);

LinearLayout layout = (LinearLayout) findViewById(R.id.chart3);

layout.addView(mChartView);
代码片段 13. 在样本应用的 Android 布局中添加条形图 ++

最后,如代码片段所示,条形图可以嵌入到 chart3 线性布局中。
生成的图表显示在以下屏幕截图中。

图 5. 使用条形图进行销售对比

在 Activity 中嵌入多个图表

利用 Android 的 UI 布局技术,我们可以将多个 AChartEngine 图表添加到同一个 Activity 中,或布局中的任何占位符位置。下面的代码片段演示了如何将前面讨论过的所有图表添加到单个 Activity 布局中。

<?xml version="1.0" encoding="utf-8"?>

	<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

	android:layout_width="fill_parent"

	android:layout_height="fill_parent"

	android:orientation="vertical"

	android:fillViewport="true">

 

<LinearLayout

	android:layout_height="wrap_content"

	android:layout_width="fill_parent"

	android:orientation="vertical"

	android:weightSum="1"

	android:gravity="center"

	android:background="@android:color/transparent">

<TextView

	android:layout_width="261dp"

	android:layout_height="104dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Menu Items Pie Chart"

	android:gravity="center"

	android:id="@+id/textView" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart1"

	android:layout_gravity="center_horizontal"

	android:background="@android:color/transparent"></LinearLayout>

<TextView

	android:layout_width="268dp"

	android:layout_height="104dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Sales Trend"

	android:gravity="center"

	android:id="@+id/textView2" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart2"

	android:layout_gravity="center_horizontal"></LinearLayout>

<TextView

	android:layout_width="344dp"

	android:layout_height="122dp"

	android:textAppearance="?android:attr/textAppearanceLarge"

	android:text="Sales Comparison Chart"

	android:gravity="center"

	android:id="@+id/textView3" />

<LinearLayout

	android:orientation="vertical"

	android:layout_width="600dp"

	android:layout_height="400dp"

	android:id="@+id/chart3"

	android:layout_gravity="center_horizontal"></LinearLayout>

	</LinearLayout>

	</ScrollView>
代码片段 14. 样本应用中显示多个图表的布局 ++

生成的视图显示在以下屏幕截图中(纵向模式)。滚动视图会自动处理触摸滚动导航。

图 6. 在 Android Activity 中嵌入的多个图表

总结

本文讨论了 Android 中可用的各种图表选项,权衡了各自的优缺点。我们使用 Android 中一个流行的图表库 AChartEngine,通过一个餐厅样本应用演示了如何添加饼图、折线图和条形图。讨论了不同的图表自定义和布局问题。

关于作者

Ashok Emani 是 Intel 软件和服务部门的一名软件工程师。他目前从事 Intel® Atom™ 处理器规模的启用项目。

声明

本文档中的信息是与英特尔产品相关提供的。本文档不授予任何明示或暗示的、通过禁止反悔或其他方式的许可,任何知识产权。除英特尔就此类产品提供的销售条款和条件外,英特尔不承担任何责任,并否认与英特尔产品的销售和/或使用相关的任何明示或暗示的保证,包括关于特定用途适用性、适销性或侵犯任何专利、版权或其他知识产权的保证。

除非 Intel 书面同意,否则 Intel 产品不设计也不用于任何可能导致人员伤亡的应用程序。

英特尔可随时更改规格和产品描述,恕不另行通知。设计人员不得依赖标记为“保留”或“未定义”的任何功能或说明的缺失或特征。英特尔为将来定义保留这些,并且对于因将来对其进行的更改而产生的冲突或不兼容性不承担任何责任。此处信息可能会更改,恕不另行通知。请勿使用此信息来最终确定设计。

本文档中描述的产品可能包含已知为勘误的设计缺陷或错误,这可能导致产品偏离已发布的规范。当前的已表征勘误可应要求提供。

请联系您当地的英特尔销售办事处或您的经销商以获取最新的规范,并在下订单前进行咨询。

可以通过致电 1-800-548-4725 或访问以下网址获取本文档中引用的具有订购号的文档副本或其他英特尔文献: http://www.intel.com/design/literature.htm
性能测试中使用的软件和工作负载可能已针对英特尔微处理器上的性能进行了优化。性能测试(如 SYSmark* 和 MobileMark*)是使用特定的计算机系统、组件、软件、操作和功能来衡量的。对这些因素中的任何一个进行更改都可能导致结果有所不同。您应该查阅其他信息和性能测试,以协助您全面评估您计划购买的产品,包括该产品与其他产品结合使用的性能。
本文档中重印的任何软件源代码均根据软件许可证提供,并且只能根据该许可证的条款使用或复制。

© . All rights reserved.