使用 Embedded Chart 自定义图表控件和背景图

 

在ACE 中,Embedded Chart实际上是一个 GraphicalView对象。与一般的Chart不同,它可以嵌入到另一个Activity中(其实就是一个普通的 view),而不必通过Intent来调用。这样做的好处在于,我们可以更灵活地定制这个GraphicalView ,比如在图表中放置一些其他的view,比如按钮、图片等。

下面我们演示如何使用 Embedded Chart。 可以看到,在这个自定义的折线图中,我们不但在GraphicalView上加入了一个Label控件和一个按钮,甚至还显示了自己的背景图。

 

AndroidMainifest.xml

在其中加入一个新的Activity,比如就叫做test.ace.EmbeddedChart:

<activity android:name="test.ace.EmbeddedChart"/>

这是一个普通的Activity类,我们在其中嵌入一个GraphicalView,以演示EmbeddedChart 的例子。下面我们来实现这个Activity。

Layout 文件

一个Activity一个xml布局文件,这里也不例外,我们把它命名为embeddedchart.xml,放在res/layout 目录下:

 <?xml version="1.0" encoding="utf-8"?>
<!-- 注意 android:background 属性的使用,为 Activity 加了一个背景图 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent" android:background="@drawable/icon"
    android:layout_height="fill_parent">

    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Embedded Chart 演示" />    
    

    <Button android:id="@+id/button1" android:text="button1"
            android:layout_width="wrap_content"    android:layout_height="wrap_content" />

     <!-- 这个 LinearLayout 用于放置 GraphicalView -->
    <LinearLayout android:id="@+id/chart" android:orientation="horizontal"
        android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" />
</LinearLayout>

EmbeddedChart.java

这个就是Activity 类的实现,在其中我们用GraphicalView 生成了一个折线图并嵌入其中:

首先我们声明几个成员变量:

privateXYMultipleSeriesDataset ds;

privateXYMultipleSeriesRenderer render;

private XYSeries series;

private GraphicalView gv;

 

private XYSeriesRenderer xyRender;

 

除了private GraphicalView gv 是Embedded Chart 特别要用到的之外,所有变量都是我们前面画柱状图和折线图中已经用到过的。

接下来是两个特殊方法:

protected voidonSaveInstanceState(Bundle outState) {

Log.i("onSaveInstanceState","onSaveInstanceState");

super.onSaveInstanceState(outState);

outState.putSerializable("dataset", ds);

outState.putSerializable("renderer", render);

outState.putSerializable("current_series", series);

outState.putSerializable("current_renderer", xyRender);

}

// 恢复 Activity 时,反序列化已保存的数据。

protected voidonRestoreInstanceState(Bundle savedState) {

Log.i("onRestoreInstanceState","onRestoreInstanceState");

super.onRestoreInstanceState(savedState);

ds = (XYMultipleSeriesDataset) savedState.getSerializable("dataset");

render = (XYMultipleSeriesRenderer) savedState.getSerializable("renderer");

series = (XYSeries) savedState.getSerializable("current_series");

xyRender = (XYSeriesRenderer) savedState.getSerializable("current_renderer");

}

这两个方法是专门用于在Activity挂起操作、唤醒操作时使用的。比如程序运行过程中用户按下了Home键或接听键(挂起),以及Activity被挂起后又再次被启动(唤醒)。

onSaveInstanceState 方法在挂起时被调用,我们在这里使用序列化方法(putSerializable方法)把Activity的成员变量储存到Bundle。

onRestoreInstanceState 方法在 Activity 唤醒时调用,在此我们使用反序列化方法(getSerializable方法)从Bundle中恢复成员变量的值。

此外,还有两个方法也是成对使用的。

// 注意,在调用 onCreate 之后会调用 onResume

protected void onResume() {

Log.i("onResume","onResume");

super.onResume();

if(ds==null)getDataset();

if(render==null)getRenderer();

if (gv == null) {

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

gv = ChartFactory.getLineChartView(this, ds, render);

layout.addView(gv, newLayoutParams(LayoutParams.FILL_PARENT,

LayoutParams.FILL_PARENT));

} else {

// 绘制图形

gv.repaint();

}

}

// 注意每次startActivity(this,EmbeddedChart.class) 之后会调用 onCreate

protected void onCreate(BundlesavedInstanceState) {

Log.i("onCreate","onCreate");

// 初始化 Activity 视图

super.onCreate(savedInstanceState);

setContentView(R.layout.embeddedchart);

}

一般来说,只要用startActivity方法启动的Activity,都会依次调用该Activity的onCreate方法和onResume方法。

onCreate方法很简单就不说了。在onResume方法中,我们调用getDataset方法构造了折线图的点数据,用getRenderer方法构造了折线图的Renderer,然后用ChartFactory.getLineChartView构造了一个GraphicalView,最后把这个GraphicalView 加到id为chart的LinearLayout中。于是在 Activity 上显示了折线图。

最后是getDataset和getRenderer 方法的实现:

privateXYMultipleSeriesDataset getDataset() {

        ds = newXYMultipleSeriesDataset();

        final int nr = 10;// 每个系列种包含10个随机数

        Random r = new Random();

        for (int i = 0; i < 1;i++) {

        // 新建一个系列(线条)

        series = new XYSeries("Series" + (i + 1));

          for (int k = 0; k < nr;k++) {

          int x=r.nextInt()%10;// x:0-10之间的随机整数

          inty=50+r.nextInt()%50;// y:50-100之间的随机整数

            series.add(x,y);// 往系列中加入一个随机分布的点

          }

          // 把添加了点的折线放入dataset

          ds.addSeries(series);

        }

       

        return ds;

     }

    publicXYMultipleSeriesRenderer getRenderer() {

    // 新建一个xymultipleseries

        render = newXYMultipleSeriesRenderer();

        render.setAxisTitleTextSize(16); // 设置坐标轴标题文本大小

        render.setChartTitleTextSize(20); // 设置图表标题文本大小

        render.setLabelsTextSize(15); // 设置轴标签文本大小

        render.setLegendTextSize(15); // 设置图例文本大小

        render.setMargins(new int[] {20, 30, 15,0}); // 设置4边留白

        render.setPanEnabled(false, false); // 设置x,y坐标轴不会因用户划动屏幕而移动

        // 设置4边留白透明

        //

        render.setMarginsColor(Color.argb(0,0xff, 0, 0));

        render.setBackgroundColor(Color.TRANSPARENT); // 设置背景色透明

        render.setApplyBackgroundColor(true); // 使背景色生效

        // 设置一个系列的颜色为蓝色

        xyRender = newXYSeriesRenderer();

        xyRender.setColor(Color.BLUE);

        // 往xymultiplerender中增加一个系列

        render.addSeriesRenderer(xyRender);

        return render;

      }

这两个方法在前面《使用 AChartEngine 画折线图》已有介绍,就不多说了。唯一值得注意的是,在使用setMarginsColor 方法设置4边背景色透明时,不能使用 Color.TRANSPARENT 或者 DefaultRenderer.NO_COLOR,这两个透明色在setMarginsColor 方法中是无效的,要用该方法设置4边透明只能用 Color.argb 方法。 argb (int alpha, int red, int green, int blue) 方法的第1个参数alpha值为00时可以获得透明色,其他颜色值任意,例如:0x00ff0000。而setBackgroundColor 方法中 Color.TRANSPARENT 是有效的——它可以把 chart 的中心区域的背景设置为透明色。不知是否是 bug。

 

EmbeddedChart的调用

要使用这个EmbeddedChart类跟一般的Activity没有任何区别,直接在另一个Activity中使用下面的语句:

intent=new Intent(this,EmbeddedChart.class);

startActivity(intent);

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭