这段时间项目中要用到报表类的统计图,android在统计这快提供了丰富的表图插件,那就是我们很熟悉的AcharEngine,它功能强大,支持散点图、折线图、饼图、气泡图、柱状图、短棒图、仪表图等多种图表。该项目地址位于: http://code.google.com/p/achartengine/
今天我们要实现的就是,把上面的图表嵌入到一个Activity中,然后自定义图表控件和背景等等!因此我们要用到Embedded Chart,这个chart就可以嵌入到Activity中,而不用通过Intent来调用,它实际上是一个 GraphicalView对象。通过这个View就可以实现自定义。比如添加label、按钮、图片等。
先看看效果图:
AndroidMainifest.xml
在其中加入一个新的Activity,比如就叫做.SphChart:
<activity android:name=".SphChart"></activity>
这是一个普通的Activity类,我们在其中嵌入一个GraphicalView,以演示EmbeddedChart 的例子。下面我们来实现这个Activity。
Layout 文件
一个Activity一个xml布局文件,这里也不例外,我们把它命名为sph_embeddedchart.xml,放在res/layout 目录下:
1 <?xml version="1.0" encoding="utf-8"?> 2 <!-- 注意 android:background 属性的使用,为 Activity 加了一个背景图 --> 3 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 4 android:layout_width="fill_parent" 5 android:layout_height="fill_parent" 6 android:background="@color/LightSteelgreen" 7 android:orientation="vertical" > 8 9 <LinearLayout 10 android:layout_width="fill_parent" 11 android:layout_height="wrap_content" 12 android:layout_marginTop="10dip" 13 android:gravity="center_horizontal" 14 android:orientation="horizontal" > 15 16 <!-- <Button 17 android:id="@+id/day" 18 android:layout_width="125dip" 19 android:layout_height="wrap_content" 20 android:background="@drawable/btn_pink" 21 android:text="日测量图" 22 android:textColor="@color/white" /> --> 23 24 <Button 25 android:id="@+id/week" 26 android:layout_width="125dip" 27 android:layout_height="wrap_content" 28 android:background="@drawable/btn_pink" 29 android:text="周测量图" 30 android:textColor="@color/white" /> 31 32 <Button 33 android:id="@+id/mounth" 34 android:layout_width="125dip" 35 android:layout_height="wrap_content" 36 android:background="@drawable/btn_pink" 37 android:text="月测量图" 38 android:textColor="@color/white" /> 39 </LinearLayout> 40 <!-- 这个 LinearLayout 用于放置 GraphicalView --> 41 42 <LinearLayout 43 android:id="@+id/chart" 44 android:layout_width="fill_parent" 45 android:layout_height="fill_parent" 46 android:layout_gravity="center" 47 android:orientation="horizontal" /> 48 49 </LinearLayout>
SphChart.java
1 public class SphChart extends Activity implements OnClickListener { 3 private XYMultipleSeriesDataset ds; 4 5 private XYMultipleSeriesRenderer render; 6 7 private XYSeries series; 8 9 private GraphicalView gv; 10 11 private XYSeriesRenderer xyRender; 12 13 private Button bt_week, bt_mounth; 14 private String[] titles = new String[] { "收缩压(mmHg)", "脉搏(次/分)", 15 "舒张压(mmHg)", "正常" }; 16 private int[] colors = new int[] { Color.RED, Color.GREEN, Color.BLUE, 17 Color.YELLOW }; 18 19 // private DataBaseOpenHelper helper; 20 // private SQLiteDatabase sdb = helper.getReadableDatabase(); 21 // private Cursor cur = sdb.query("sph", null, null, null, null, null, 22 // null); 23 @Override 24 protected void onCreate(Bundle savedInstanceState) { 25 super.onCreate(savedInstanceState); 26 setContentView(R.layout.sph_embeddedchart); 27 getControlsId(); 28 setOnClick(); 29 30 }
31 //onRestoreInstanceState 方法在 Activity 唤醒时调用,在此我们使用反序列化方法(getSerializable方法)从Bundle中恢复成员变量的值。 32 @Override 33 protected void onRestoreInstanceState(Bundle savedState) { 34 Log.i("onRestoreInstanceState", "onRestoreInstanceState"); 35 36 super.onRestoreInstanceState(savedState); 37 38 ds = (XYMultipleSeriesDataset) savedState.getSerializable("dataset"); 39 40 render = (XYMultipleSeriesRenderer) savedState 41 .getSerializable("renderer"); 42 43 series = (XYSeries) savedState.getSerializable("current_series"); 44 45 xyRender = (XYSeriesRenderer) savedState 46 .getSerializable("current_renderer"); 47 } 48
//在onResume方法中,我们调用getDataset方法构造了折线图的点数据,用getRenderer方法构造了折线图的Renderer,然后用ChartFactory.getLineChartView
//构造了一个GraphicalView,最后把这个GraphicalView 加到id为chart的LinearLayout中。于是在 Activity 上显示了折线图。
49 protected void onResume() { 50 51 Log.i("onResume", "onResume"); 52 53 super.onResume(); 54 55 if (ds == null) 56 getDataset(); 57 if (render == null) 58 getRenderer(); 59 60 if (gv == null) { 61 62 LinearLayout layout = (LinearLayout) findViewById(R.id.chart); 63 64 gv = ChartFactory.getLineChartView(this, ds, render); 65 66 layout.addView(gv, new LayoutParams(LayoutParams.FILL_PARENT, 67 68 LayoutParams.FILL_PARENT)); 69 70 } else { 71 72 // 绘制图形 73 74 gv.repaint(); 75 76 } 77 78 } 79
// onSaveInstanceState 方法在挂起时被调用,我们在这里使用序列化方法(putSerializable方法)把Activity的成员变量储存到Bundle。 80 @Override 81 protected void onSaveInstanceState(Bundle outState) { 82 super.onSaveInstanceState(outState); 83 Log.i("onSaveInstanceState", "onSaveInstanceState"); 84 85 super.onSaveInstanceState(outState); 86 87 outState.putSerializable("dataset", ds); 88 89 outState.putSerializable("renderer", render); 90 91 outState.putSerializable("current_series", series); 92 93 outState.putSerializable("current_renderer", xyRender); 94 } 95 96 private XYMultipleSeriesDataset getDataset() { 97 ds = new XYMultipleSeriesDataset(); 98 final int nr = 10;// 每个系列种包含10个随机数 99 for (int i = 0; i < titles.length; i++) { 100 // 新建一个系列(线条) 101 series = new XYSeries(titles[i]); 102 103 switch (i) { 104 case 0: 105 for (int k = 1; k < nr; k++) { 106 int m = (int) Math.rint(Math.random() * (180 - 100) + 100); 107 series.add(k, m); 108 } 109 ds.addSeries(series); 110 break; 111 case 1: 112 for (int k = 1; k < nr; k++) { 113 int m = (int) Math.rint(Math.random() * (80 - 60) + 60); 114 115 series.add(k, m); 116 } 117 ds.addSeries(series); 118 break; 119 case 2: 120 121 for (int k = 1; k < nr; k++) { 122 int m = (int) Math.rint(Math.random() * (100 - 60) + 60); 123 series.add(k, m); 124 } 125 ds.addSeries(series); 126 break; 127 case 3: 128 for (int k = 1; k < nr; k++) { 129 int zhenchang = 135; 130 series.add(k, zhenchang); 131 } 132 ds.addSeries(series); 133 break; 134 default: 135 break; 136 } 137 138 } 139 140 return ds; 141 142 } 143 144 @SuppressLint({ "ResourceAsColor", "ResourceAsColor" }) 145 public XYMultipleSeriesRenderer getRenderer() { 146 147 // 新建一个xymultipleseries 148 149 render = new XYMultipleSeriesRenderer(); 150 render.setAxisTitleTextSize(16); // 设置坐标轴标题文本大小 151 render.setChartTitleTextSize(20); // 设置图表标题文本大小 152 render.setChartTitle("当日测量血压数据值"); 153 render.setLabelsTextSize(15); // 设置轴标签文本大小 154 render.setLegendTextSize(15); // 设置图例文本大小 155 render.setMargins(new int[] { 20, 30, 15, 15 }); // 设置4边留白 156 render.setPanEnabled(false, false); // 设置x,y坐标轴不会因用户划动屏幕而移动 157 render.setMarginsColor(Color.argb(0, 0xff, 0, 0));// 设置4边留白透明 158 render.setBackgroundColor(Color.TRANSPARENT); // 设置背景色透明 159 render.setApplyBackgroundColor(true); // 使背景色生效 160 render.setXLabels(10);// 设置X轴显示12个点,根据setChartSettings的最大值和最小值自动计算点的间隔 161 render.setYLabels(12);// 设置y轴显示10个点,根据setChartSettings的最大值和最小值自动计算点的间隔 162 render.setXLabelsAlign(Align.RIGHT);// 刻度线与刻度标注之间的相对位置关系 163 render.setYLabelsAlign(Align.CENTER);// 刻度线与刻度标注之间的相对位置关系 164 // render.setZoomButtonsVisible(true);// 是否显示放大缩小按钮 165 render.setShowGrid(true);// 是否显示网格 166 render.setGridColor(R.color.white);// 设置网格颜色 167 render.setAxesColor(R.color.black);// 设置X.y轴颜色 168 render.setFitLegend(true);// 设置自动按比例缩放 169 render.setYAxisMax(200.0); // 设置Y轴最大值 170 render.setYAxisMin(40.0); // 设置Y轴最小值 171 172 // 设置x,y轴上的刻度的颜色 173 render.setLabelsColor(Color.BLACK); 174 render.setXTitle("测量次数"); 175 render.setYTitle("测量数值"); 176 177 render.setLabelsColor(R.color.red); 178 // render.setYLabelsColor(1, R.color.black); 179 // 设置一个系列的颜色为红色 180 for (int i = 0; i < titles.length; i++) { 181 xyRender = new XYSeriesRenderer(); 182 xyRender.setPointStyle(PointStyle.CIRCLE); 183 xyRender.setColor(colors[i]);// 设置线图颜色 184 xyRender.setFillPoints(true);// 设置为实心点 185 render.addSeriesRenderer(xyRender);// 添加到render中 186 } 187 return render; 188 189 } 190 191 private void getControlsId() { 192 // bt_day = (Button) findViewById(R.id.day); 193 bt_week = (Button) findViewById(R.id.week); 194 bt_mounth = (Button) findViewById(R.id.mounth); 195 // back_bt = (Button) findViewById(R.id.back); 196 // devices_bt = (Button) findViewById(R.id.device_paired); 197 // devices_bt.setVisibility(View.GONE); 198 } 199 200 @Override 201 protected void onStop() { 202 // TODO Auto-generated method stub 203 super.onStop(); 204 } 205 206 private void setOnClick() { 207 bt_week.setOnClickListener(this); 208 bt_mounth.setOnClickListener(this); 209 // back_bt.setOnClickListener(this); 210 } 211 212 @Override 213 public void onClick(View v) { 214 Intent intent = new Intent(); 215 switch (v.getId()) { 216 217 case R.id.week: 218 intent = new Intent(SphChart.this, SphWeekData.class); 219 startActivity(intent); 220 SphChart.this.finish(); 221 break; 222 case R.id.mounth: 223 intent = new Intent(SphChart.this, SphMounthData.class); 224 startActivity(intent); 225 SphChart.this.finish(); 226 break; 227 case R.id.back: 228 intent = new Intent(SphChart.this, SphModule.class); 229 startActivity(intent); 230 break; 231 default: 232 break; 233 } 234 } 235