最近的项目需要显示统计报表,完全自己画太费时间,搜索了一下,找到了aChartEngine。项目主页:http://code.google.com/p/achartengine/,而美工给我的图是这样的: , 显然,下载编译好的jar包不能满足我的需求,所以我下的是源代码,稍稍做了些小修改。 现在我们的需求是这样:数据比较多,每天一条,一年就是365条,不可能一起都显示出来,用户可以左右拉拖动来查看之前的和之后的数据,就是动态加载报表的数据,还有一点,纵座标,我这里的温度是体温,一般不会差距很大,但是如果是其他的,例如体重,人和人的差距就很大了,所以,纵座标的范围也需要动态控制,另外,我们的项目不允许缩放报表。 在拖动Chart的时候,会触发PanListener的panApplied方法,所以,我们只要在这个方法里,取到当前的横座标的取值范围,再根据这个范围去数据库查找数据,然后把数据加入XYMultipleSeriesDataset里,就可以了,至于Y座标的范围,可以查询数据库,取出横座标范围内的最大值和最小值。
final GraphicalView chartView=temperatureChart.getView();
layout_chart.addView(chartView);
chartView.addPanListener(new PanListener() {
@Override
public void panApplied() {
// TODO Auto-generated method stub
double[] range=chartView.getRange();
Date maxDate=new Date();
Date minDate=new Date();
maxDate.setTime((long)range[1]+1000*60*60*24*2);
minDate.setTime((long)range[0]-1000*60*60*24*2);
temperatureChart.loadData(minDate,maxDate);
}
});
temperatureChart是一个继续自AbstractChart的类的实例。这里的AbstractChart并非org.achartengine.chart.AbstractChart,而是官方Demo里的org.achartengine.chartdemo.demo.chart.AbstractChart. 解释一下,我这里的时间为什么要最小值减两天,最大值加两天,这是因为当用户手指离开屏幕,最后一次执行panApplied方法后,UI是不会更改的,当用户再次把手指放到屏幕上,触发org.achartengine.TouchHandler里的方法时,才会重新绘图,更新UI,所以如果读取的范围不大一点,用户最终看到的是上一次panApplied方法执行后的结果,而不是最后一次,导致左右边会有空白,没有数据。其实更好的方法,应该是改源码,增加个类似Adapter的notifyDataSetChanged()方法,通知更新UI,但是稍稍复杂点。 GraphicalView里的getRange方法,功能是获取横纵座标的范围:
/**
* 获取表横纵座标的范围,返回的数组,4个值分别为
* x最小值,x最大值,y最小值,y最大值
* @return
*/
public double[] getRange()
{
double[] range=new double[4];
XYMultipleSeriesRenderer renderer=(XYMultipleSeriesRenderer)mRenderer;
range[0]=renderer.getXAxisMin();
range[1]=renderer.getXAxisMax();
range[2]=renderer.getYAxisMin();
range[3]=renderer.getYAxisMax();
return range;
}
loadData方法:
/**
* 载入指定时期的数据
* @param start
* @param end
*/
public void loadData(Date start, Date end) {
dataset.removeAllSeries();
List signList = healthDB.getSignList(HealthSigns.TEMPERATURE, start, end);
TimeSeries series = new TimeSeries("体温变化曲线");
for (HealthSigns sign : signList) {
series.add(sign.getDate(), sign.getData());
}
dataset.addSeries(series);
float yAxisMax=healthDB.getMaxIn(HealthSigns.TEMPERATURE, start, end);
float yAxisMin=healthDB.getMinIn(HealthSigns.TEMPERATURE, start, end);
renderer.setYAxisMax(yAxisMax);
renderer.setYAxisMin(yAxisMin);
}