使用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:
package com.example.mychartdemo; import java.util.Timer;
import java.util.TimerTask; import org.achartengine.GraphicalView; import com.ivan.chart.ChartService; import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout; public class MainActivity extends Activity { private LinearLayout mLeftCurveLayout;//存放左图表的布局容器
private LinearLayout mRightCurveLayout;//存放右图表的布局容器
private GraphicalView mView, mView2;//左右图表
private ChartService mService, mService2;
private Timer timer; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); mLeftCurveLayout = (LinearLayout) findViewById(R.id.left_temperature_curve);
mRightCurveLayout = (LinearLayout) findViewById(R.id.right_temperature_curve); mService = new ChartService(this);
mService.setXYMultipleSeriesDataset("左温度曲线");
mService.setXYMultipleSeriesRenderer(100, 100, "左温度曲线", "时间", "温度",
Color.RED, Color.RED, Color.RED, Color.BLACK);
mView = mService.getGraphicalView(); mService2 = new ChartService(this);
mService2.setXYMultipleSeriesDataset("右温度曲线");
mService2.setXYMultipleSeriesRenderer(100, 100, "右温度曲线", "时间", "温度",
Color.RED, Color.RED, Color.RED, Color.BLACK);
mView2 = mService2.getGraphicalView(); //将左右图表添加到布局容器中
mLeftCurveLayout.addView(mView, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
mRightCurveLayout.addView(mView2, new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendMessage(handler.obtainMessage());
}
}, 10, 1000);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
} private int t = 0;
private Handler handler = new Handler() {
@Override
//定时更新图表
public void handleMessage(Message msg) {
mService.updateChart(t, Math.random() * 100);
mService2.updateChart(t, Math.random() * 100);
t+=5;
}
}; @Override
protected void onDestroy() {
super.onDestroy();
if (timer != null) {
timer.cancel();
}
} }
ChartService:
package com.ivan.chart; import java.util.List; import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint.Align; public class ChartService { private GraphicalView mGraphicalView;
private XYMultipleSeriesDataset multipleSeriesDataset;// 数据集容器
private XYMultipleSeriesRenderer multipleSeriesRenderer;// 渲染器容器
private XYSeries mSeries;// 单条曲线数据集
private XYSeriesRenderer mRenderer;// 单条曲线渲染器
private Context context; public ChartService(Context context) {
this.context = context;
} /**
* 获取图表
*
* @return
*/
public GraphicalView getGraphicalView() {
mGraphicalView = ChartFactory.getCubeLineChartView(context,
multipleSeriesDataset, multipleSeriesRenderer, 0.1f);
return mGraphicalView;
} /**
* 获取数据集,及xy坐标的集合
*
* @param curveTitle
*/
public void setXYMultipleSeriesDataset(String curveTitle) {
multipleSeriesDataset = new XYMultipleSeriesDataset();
mSeries = new XYSeries(curveTitle);
multipleSeriesDataset.addSeries(mSeries);
} /**
* 获取渲染器
*
* @param maxX
* x轴最大值
* @param maxY
* y轴最大值
* @param chartTitle
* 曲线的标题
* @param xTitle
* x轴标题
* @param yTitle
* y轴标题
* @param axeColor
* 坐标轴颜色
* @param labelColor
* 标题颜色
* @param curveColor
* 曲线颜色
* @param gridColor
* 网格颜色
*/
public void setXYMultipleSeriesRenderer(double maxX, double maxY,
String chartTitle, String xTitle, String yTitle, int axeColor,
int labelColor, int curveColor, int gridColor) {
multipleSeriesRenderer = new XYMultipleSeriesRenderer();
if (chartTitle != null) {
multipleSeriesRenderer.setChartTitle(chartTitle);
}
multipleSeriesRenderer.setXTitle(xTitle);
multipleSeriesRenderer.setYTitle(yTitle);
multipleSeriesRenderer.setRange(new double[] { 0, maxX, 0, maxY });//xy轴的范围
multipleSeriesRenderer.setLabelsColor(labelColor);
multipleSeriesRenderer.setXLabels(10);
multipleSeriesRenderer.setYLabels(10);
multipleSeriesRenderer.setXLabelsAlign(Align.RIGHT);
multipleSeriesRenderer.setYLabelsAlign(Align.RIGHT);
multipleSeriesRenderer.setAxisTitleTextSize(20);
multipleSeriesRenderer.setChartTitleTextSize(20);
multipleSeriesRenderer.setLabelsTextSize(20);
multipleSeriesRenderer.setLegendTextSize(20);
multipleSeriesRenderer.setPointSize(2f);//曲线描点尺寸
multipleSeriesRenderer.setFitLegend(true);
multipleSeriesRenderer.setMargins(new int[] { 20, 30, 15, 20 });
multipleSeriesRenderer.setShowGrid(true);
multipleSeriesRenderer.setZoomEnabled(true, false);
multipleSeriesRenderer.setAxesColor(axeColor);
multipleSeriesRenderer.setGridColor(gridColor);
multipleSeriesRenderer.setBackgroundColor(Color.WHITE);//背景色
multipleSeriesRenderer.setMarginsColor(Color.WHITE);//边距背景色,默认背景色为黑色,这里修改为白色
mRenderer = new XYSeriesRenderer();
mRenderer.setColor(curveColor);
mRenderer.setPointStyle(PointStyle.CIRCLE);//描点风格,可以为圆点,方形点等等
multipleSeriesRenderer.addSeriesRenderer(mRenderer);
} /**
* 根据新加的数据,更新曲线,只能运行在主线程
*
* @param x
* 新加点的x坐标
* @param y
* 新加点的y坐标
*/
public void updateChart(double x, double y) {
mSeries.add(x, y);
mGraphicalView.repaint();//此处也可以调用invalidate()
} /**
* 添加新的数据,多组,更新曲线,只能运行在主线程
* @param xList
* @param yList
*/
public void updateChart(List<Double> xList, List<Double> yList) {
for (int i = 0; i < xList.size(); i++) {
mSeries.add(xList.get(i), yList.get(i));
}
mGraphicalView.repaint();//此处也可以调用invalidate()
}
}
布局文件:activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="20dp"
android:layout_weight="1"
android:orientation="vertical" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="左温度曲线" /> <LinearLayout
android:id="@+id/left_temperature_curve"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical" > <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="右温度曲线" /> <LinearLayout
android:id="@+id/right_temperature_curve"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout> </LinearLayout>
详细说明见注释。
AChartEngine功能真的很强大,之前一直想要自己来画曲线图,浪费了几天功夫。所以说,站在巨人的肩膀上是很重要的。对于程序员,有一句很重要的话,叫做不要重复造轮子。但是,要使用别人的轮子,必须先要理解透彻,否则很难实现漂亮的效果。
由于笔者水平有限,如有错漏之处在所难免,欢迎读者批评指正,感激不尽!
原创文章,转载请注明出处。
全文完
使用AChartEngine画动态曲线图的更多相关文章
- achartengine画出动态折线图
achartengine画出动态折线图的效果最近有个项目需要用到实时曲线图,我也上网搜索了一下,最后还是选择使用achartengine这个现成的东西,毕竟自己再canvas一下实在是太麻烦,而且项目 ...
- Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)
图形报表很常用,因为展示数据比较直观,常见的形式有很多,如:折线图.柱形图.饼图.雷达图.股票图.还有一些3D效果的图表等. Android中也有不少第三方图表库,但是很难兼容各种各样的需求. 如果第 ...
- matplotlib 画动态图以及plt.ion()和plt.ioff()的使用
学习python的道路是漫长的,今天又遇到一个问题,所以想写下来自己的理解方便以后查看. 在使用matplotlib的过程中,常常会需要画很多图,但是好像并不能同时展示许多图.这是因为python可视 ...
- 程序猿的浪漫:用python画动态爱心
初级画心 学Python,感觉你们的都好复杂,那我来个简单的,我是直接把心形看作是一个正方形+两个半圆:
- Android 之surfaceView (画动态圆圈)
通过之前介绍的如何自定义View, 我们知道使用它可以做一些简单的动画效果.它通过不断循环的执行View.onDraw方法,每次执行都对内部显示的图形做一些调整,我们假设 onDraw方法每秒执行 ...
- Python学习-使用matplotlib画动态多图
最近常常使用matplotlib进行数学函数图的绘制,可是怎样使用matplotlib绘制动态图,以及绘制动态多图.直到今天才学会. 1.參考文字 首先感谢几篇文字的作者.帮我学会了怎样绘制.大家也能 ...
- 在.NET MVC 中使用Highcharts+Ajax+Json生成动态曲线图,柱状图,饼图
开发背景: 今天在做一个关于商城后台金额报表统计的功能,为了让数据直观明了并且这个报表还需要在手机端自适应所以我决定采用HIghCharts插件下的的报表,大家也可以去了解一下免费开源主要是好看. 首 ...
- CSS+transform画动态表情
先给大家看下画完后是什么样子: 代码看这里: html代码: <body> <div class="emoji emoji_like"> <div c ...
- Excel2010画动态甘特图
哈哈!你居然真的看简介点进来啦,我也想八一八Henry gantt本人的故事,可是我查了好些资料,一个槽点都没有发现,不过人生经历还是蛮拼的: 此人活了58年,前半生就是一个中规中距的机械工程师&am ...
随机推荐
- 异步IO类
也学习多线程一段时间了,也写了几个简单实用的功能类,也意思到细节的处理的重要性,现在就让我们来写一个稍稍更有用的异步IO的类. 本来想参考Java NIO 中的类,Java NIO作为新io包,本身提 ...
- ibatis 参数之模糊查询
因项目需要最近使用ibatis,在使用查询语句的时候,想着通用性所以没有在配置文件里用N多的and 语句,而是如下: <select id="getUsersList" re ...
- SharpMap开发教程——图层标注
在GIS开发中,根据图层属性字段对要素进行标注(图层标注)是一项常规的.必备的功能.在基于SharpMap开发GIS应用时,也可以方便的实现该功能. 1.加载Shapefile图层数据 SharpMa ...
- SSL证书 .pem转.pfx
使用OpenSSL来进行转换 OpenSSL官网没有提供windows版本的安装包,可以选择其他开源平台提供的工具.例如 http://slproweb.com/products/Win32OpenS ...
- 数独高阶技巧入门之三——Fish
术语Fish代表了一组工作原理相同的关于特定候选数的解题技巧(Fish技巧直接产生自数独规则——每个单元内的数字都不能重复),Fish家族成员包括“体型”从小到大的X-Wing.Swordfish. ...
- CLR via C# 读书笔记-27.计算限制的异步操作(上篇)
前言 学习这件事情是一个习惯,不能停...另外这篇已经看过两个月过去,但觉得有些事情不总结跟没做没啥区别,遂记下此文 1.CLR线程池基础 2.ThreadPool的简单使用练习 3.执行上下文 4. ...
- C#连接MySql数据库代码
之前学JAVA的时候,老师讲数据库的时候,讲到可以用一个类来连接数据库,叫做Dao层,今天要用C#做上位机,也有一些数据要写到数据库中去,我就想,能不能也给C#写一个这样的Dao层来连接数据库,我就去 ...
- 【OCP|052】iZ0-052最新题库及答案整理-第9题
9.Which is true about the Automatic Diagnostic Repository (ADR)? A) It includes diagnostic data for ...
- vue.js 知识点(四)
看完了vue.js的官方文档,大概对这些知识有了那么一点的了解了,但是很多具体的运用还不太清楚,现在就总结一下,关于其中的一些知识点的运用: v-bind: 动态绑定指令,默认情况下,是给html ...
- 迫不得已! ! 仅仅针对IE浏览器的样式,尤其是IE8及以下
IE10不会起作用,IE9,8,7,6,5都可以 <html> <head> <title>IE打开就是蓝色背景,白色的字体</title> <! ...