Android使用AchartEngine绘制曲线图(一个点刷新一次)
首先说明下,这个里面的代码借鉴了网上的一些资源,总的来说很感谢,我做的工作就是简化新手的使用,写一个类,然后在主界面调用显示图表就会显得非常简单,这个有个前提1.大概了解下AchatgEngine的使用,然后你的工程项目中要导入这个架包(怎么导入的我就就不说了吧,呵呵,你懂的),2.刷新效果的实现必须依赖定时任务,定时任务可以用Handler和TimeTask或者Handler和postDelayed(Runnable, long)实现,可以参考如下:
Handler和postDelayed(Runnable, long),这个实现比较简单一些。
1. 定义一个Handler类
Handler handler=new Handler(); Runnable runnable=new Runnable() { @Override public void run() { // TODO Auto-generated method stub //要做的事情 handler.postDelayed(this, 2000); } };
2. 启动计时器
handler.postDelayed(runnable, 2000);//每两秒执行一次runnable.
3. 停止计时器
handler.removeCallbacks(runnable);
三、采用Handler与timer及TimerTask结合的方法
1. 定义定时器、定时器任务及Handler句柄
private final Timer timer = new Timer(); private TimerTask task; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub // 要做的事情 super.handleMessage(msg); } };
2. 初始化计时器任务
task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Message message = new Message(); message.what = 1; handler.sendMessage(message); } };
3. 启动定时器
timer.schedule(task, 2000, 2000);
4. 停止计时器
timer.cancel();
我这里用的是task的方式,先看封装的类DynamicChart.java
package com.example.testchart; 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; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; public class DynamicChart { private XYSeries series; private XYMultipleSeriesDataset mDataset; private XYMultipleSeriesRenderer renderer; private GraphicalView chart; private Context context; private LinearLayout layout;// 相当于图表的容器 private String title = "Signal Strength";// 对应图表的标题 private int addX = -1, addY; private int[] xv = new int[100]; private int[] yv = new int[100]; public LinearLayout getLayout() { return layout; } public Context getContext() { return context; } public void setContext(Context context) { this.context = context; } public void setLayout(LinearLayout layout) { this.layout = layout; } public DynamicChart() {// 无参构造方法 super(); // TODO Auto-generated constructor stub } public DynamicChart(Context context, LinearLayout layout) {//有参构造方法 super(); this.context = context; this.layout = layout; } public void init() { // 这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线 series = new XYSeries(title); // 创建一个数据集的实例,这个数据集将被用来创建图表 mDataset = new XYMultipleSeriesDataset(); // 将点集添加到这个数据集中 mDataset.addSeries(series); // 以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄 renderer = buildRenderer(true); // 设置好图表的样式 setChartSettings(renderer, 0, 100, 0, 90); // 生成图表 chart = ChartFactory.getLineChartView(context, mDataset, renderer); // 将图表添加到布局中去 layout.addView(chart, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } /** * 基本上就是一些图标属性的设置 * * @param renderer * @param xMin * @param xMax * @param yMin * @param yMax */ private void setChartSettings(XYMultipleSeriesRenderer renderer, double xMin, double xMax, double yMin, double yMax) { // 有关对图表的渲染可参看api文档 // renderer.setMargins(new int[] { 50, 50, 50, 50 }); // // 设置图表的外边框(上/左/下/右) renderer.setChartTitle(title);// 设置图表的标题 renderer.setXTitle("波长");// 设置横坐标标题 renderer.setYTitle("A/D counts");// 设置纵坐标标题 renderer.setChartTitleTextSize(20); // 设置整个图表标题文字大小 renderer.setXAxisMin(xMin);// 设置x轴的最小值 renderer.setXAxisMax(xMax);// 设置x轴的最大值 renderer.setYAxisMin(yMin);// 设置y轴的最小值 renderer.setYAxisMax(yMax);// 设置y轴的最大值 renderer.setAxesColor(Color.BLACK);// 设置x\y轴的“直线”颜色 renderer.setLabelsColor(Color.BLACK);// 设置xy和图标标题文字颜色 renderer.setShowGrid(false);// 是否显示网格 renderer.setGridColor(Color.GRAY);// 设置网格的颜色 renderer.setAxisTitleTextSize(20); // 设置轴标题文字的大小 renderer.setXLabels(20); renderer.setYLabels(10); renderer.setXLabelsAlign(Align.CENTER); // 刻度线与刻度标注之间的相对位置关系 renderer.setYLabelsAlign(Align.RIGHT);// 刻度线与刻度标注之间的相对位置关系 renderer.setPanEnabled(false, true); // 设置是否允许XY轴方向移动 renderer.setPointSize((float) 2);//每个点所呈现的大小 renderer.setShowLegend(false);// 是否显示图例 renderer.setZoomEnabled(true);// 是否容许方法或缩小 renderer.setZoomButtonsVisible(true);// 是否显示放大缩小按钮 renderer.setApplyBackgroundColor(true); // 设置是否显示背景色 renderer.setBackgroundColor(Color.WHITE);// 设置背景颜色 renderer.setMarginsColor(Color.WHITE); // 设置外框颜色穿透背景色 } private XYMultipleSeriesRenderer buildRenderer(boolean fill) { XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer(); // 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等 XYSeriesRenderer r = new XYSeriesRenderer(); r.setColor(Color.GREEN);// 设置点的颜色 r.setPointStyle(PointStyle.CIRCLE);// 点的类型(圆形、方形或者没有) r.setFillPoints(fill); r.setLineWidth(3); renderer.addSeriesRenderer(r); return renderer; } public void updateChart(int value) { // 设置好下一个需要增加的节点 addX = 0; // addY = (int) (Math.random() * 90); addY = value; // 移除数据集中旧的点集 mDataset.removeSeries(series); // 判断当前点集中到底有多少点,因为屏幕总共只能容纳100个,所以当点数超过100时,长度永远是100 int length = series.getItemCount(); if (length > 100) { length = 100; } // 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果 for (int i = 0; i < length; i++) { xv[i] = (int) series.getX(i) + 1; yv[i] = (int) series.getY(i); } // 点集先清空,为了做成新的点集而准备 series.clear(); // 将新产生的点首先加入到点集中,然后在循环体中将坐标变换后的一系列点都重新加入到点集中 // 这里可以试验一下把顺序颠倒过来是什么效果,即先运行循环体,再添加新产生的点 series.add(addX, addY); for (int k = 0; k < length; k++) { series.add(xv[k], yv[k]); } // 在数据集中添加新的点集 mDataset.addSeries(series); // 视图更新,没有这一步,曲线不会呈现动态 // 如果在非UI主线程中,需要调用postInvalidate(),具体参考api chart.invalidate(); } }
那么在Activity中调用就很简单了,看MainActivity中的代码:
package com.example.testchart; import java.util.Timer; import java.util.TimerTask; import android.annotation.SuppressLint; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.LinearLayout; public class MainActivity extends Activity { private DynamicChart dynamicChart; private Timer timer = new Timer(); private TimerTask task = new TimerTask() { @Override public void run() { // TODO Auto-generated method stub Message message = new Message(); message.what = 1; handler.sendMessage(message); } }; @SuppressLint("HandlerLeak") private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); dynamicChart.updateChart((int) (Math.random() * 90)); }}; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.test); dynamicChart = new DynamicChart(getApplicationContext(), (LinearLayout)findViewById(R.id.chartLayout1)); dynamicChart.init(); timer.schedule(task, 500, 500); } }
当然你需要在你的视图xml文件中定义一个容器来存放图表:
<LinearLayout android:id="@+id/chartLayout1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="10dip" android:background="#FFFFFF" android:orientation="vertical" >
然后来一张效果图: