我们在安卓开发中,有时会用到统计图表的功能,而曲线绘制是其中比较典型的一种,一般是利用给定的坐标点集和安卓自带的绘图模块进行绘制,直接得到的是一张完整的静态的曲线图。但有时,我们需要动态绘制一些曲线图,就像我们打开电脑的任务管理器,里面有一个cpu使用记录的动态变化的带网格的曲线图,对于这一类的曲线绘制,安卓sdk自带的绘图模块貌似就不那么好用了。

在这里,我就利用handler+timer机制和第三方开发包achartengine实现动态绘制安卓手机充放电曲线的应用。

1、下载第三方开发包achartengine,也就是jar包,可以在网上找到下载源,我下载的是achartengine-1.1.0.jar;

2、在创建的应用工程文件中引入该jar包,以eclipse为例方法是:在包资源管理器目录中右键单击已创建的项目名称——>构建路径——>配置构建路径——>java构建路径——>库——>外部jar,然后找到achartengine包的存放路径,找到achartengine-1.1.0.jar文件,点击打开即完成了该包的引用,这时会在项目目录下出现一个名为引用的库文件,里面就是我们刚才引入的jar包。

3、接下来就可以按正常步骤开发该应用了,需要注意的是:需要在主类中引入jar中绘图需要的库文件,如下:

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;

同时需要在androidmanifest.xml文件中加上语句:             

<application
   android:icon="@drawable/ic_launcher"
   android:label="@string/app_name" >
<activity android:name="org.achartengine.graphicalactivity" />

4、接下来需要定义一些绘图的变量和样式:             

private xyseries series;
              private xymultipleseriesdataset mdataset;
              private graphicalview chart;
              private xymultipleseriesrenderer renderer;
              private context context, context1;
              private int addx = -1, addy;
              int[] xv = new int[720];// x轴数组元素个数
              int[] yv = new int[720];// y轴数组元素个数         
                  context = getapplicationcontext();
              // 这里获得main界面上的布局,下面会把图表画在这个布局里面
              linearlayout layout = (linearlayout) findviewbyid(r.id.linearlayout1);
              // 这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线
              series = new xyseries(title);
              // 创建一个数据集的实例,这个数据集将被用来创建图表
              mdataset = new xymultipleseriesdataset();
              // 将点集添加到这个数据集中
              mdataset.addseries(series);
              // 以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄
              int color = color.green;
              pointstyle style = pointstyle.circle;
              renderer = buildrenderer(color, style, true);
 
              // 设置好图表的样式(横轴时间分钟值,纵轴电压毫伏值)
              setchartsettings(renderer, "x", "y", 0, 240, 3400, 4400, color.white,color.white);
              // 生成图表
              chart = chartfactory.getlinechartview(context, mdataset, renderer);
              // 将图表添加到布局中去
              layout.addview(chart, new layoutparams(layoutparams.fill_parent, layoutparams.wrap_content));
 
               protected xymultipleseriesrenderer buildrenderer(int color,pointstyle style, boolean fill)// 配置绘图属性
              {
              xymultipleseriesrenderer renderer = new xymultipleseriesrenderer();
              // 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
              xyseriesrenderer r = new xyseriesrenderer();
              r.setcolor(color);
              r.setpointstyle(style);
              r.setfillpoints(fill);
              r.setlinewidth((float) 1);// 线粗尺寸
              renderer.addseriesrenderer(r);
              return renderer;
}
 
protected void setchartsettings(xymultipleseriesrenderer renderer,
string xtitle, string ytitle, double xmin, double xmax,
double ymin, double ymax, int axescolor, int labelscolor) {
// 有关对图表的渲染可参看api文档
renderer.setcharttitle(title);
renderer.setxtitle(xtitle);
renderer.setytitle(ytitle);
renderer.setxaxismin(xmin);
renderer.setxaxismax(xmax);
renderer.setyaxismin(ymin);
renderer.setyaxismax(ymax);
renderer.setaxescolor(axescolor);
renderer.setlabelscolor(labelscolor);
renderer.setshowgrid(true);
renderer.setgridcolor(color.green);// 曲线颜色
renderer.setxlabels(20);
renderer.setylabels(10);
renderer.setcharttitle("时间/电压变化曲线图");// 图表名称
renderer.setxtitle("时间(min)");// 横坐标名称
renderer.setytitle("电压(mv)");// 纵坐标名称
renderer.setylabelsalign(align.right);
renderer.setpointsize((float) 1.5);// 设置点的大小
renderer.setshowlegend(false);
renderer.setpanenabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
renderer.setzoomenabled(true, false);// 设置缩放,横向可以,纵向不可以
// renderer.setzoomlimits(new double[] { 0, 720, 3400, 4400 });//设置缩放的范围
// renderer.setpanlimits(new double[] { -0.5, 720, 3400, 4400
// });//设置拉动的范围
}

5、动态绘制的实现:动态绘制主要需要实现两方面的内容,一是更新绘图的方法、二是动态绘图时间任务的定义。

1)更新绘图方法:             

private void updatechart()// 更新绘图方法</strong>
{
// 设置好下一个需要增加的节点
addx = (int) (addx + 1);
addy = batteryv;
// 移除数据集中旧的点集
mdataset.removeseries(series);
// 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
int length = series.getitemcount();
if (length > 720) {
length = 720;
}
// 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
for (int i = 0; i < length; i++) {
xv[i] = (int) series.getx(i);
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();
}

2)时间任务定义:              

handler = new handler() {
@override
public void handlemessage(message msg) {
// 刷新图表
updatechart();// 电压变化曲线刷新
updatechart1();// 电量变化曲线刷新
super.handlemessage(msg);
}
};
task = new timertask()// 刷新绘图计时任务配置
{
@override
public void run() {
message message = new message();
message.what = 1;
handler.sendmessage(message);
}
};
timer.schedule(task, 0, 60000);// 以一分钟为时间间隔运行 

再发一下完整的代码:

主类:

package com.cfzz.vcd;
 
import java.io.fileoutputstream;
import java.text.simpledateformat;
import java.util.date;
import java.util.locale;
import java.util.timer;
import java.util.timertask;
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 com.cfzz.vqcd.r;
 
//import com.cfzz.wy.r;
 
import android.app.activity;
import android.content.broadcastreceiver;
import android.content.context;
import android.content.intent;
import android.content.intentfilter;
import android.graphics.bitmap;
import android.graphics.color;
import android.graphics.paint.align;
import android.os.batterymanager;
import android.os.bundle;
import android.os.handler;
import android.os.message;
import android.os.powermanager;
import android.view.keyevent;
import android.view.view;
import android.view.viewgroup.layoutparams;
import android.view.windowmanager;
import android.widget.button;
import android.widget.linearlayout;
import android.widget.textview;
import android.widget.toast;
import android.view.view.onclicklistener;
 
public class voltagechangedraw extends activity {
 
    // protected static final activity activity = null;
    private powermanager.wakelock wl;
    private timer timer = new timer();
    private long mexittime = 0;
    private timertask task, task1;
    private handler handler;
    private string title = "signal strength";
    private xyseries series, series1;
    private xymultipleseriesdataset mdataset, mdataset1;
    private graphicalview chart, chart1;
    private xymultipleseriesrenderer renderer, renderer1;
    private context context, context1;
    private int addx = -1, addy;
    private int addx1 = -1, addy1;
    private button button;
    int[] xv = new int[720];// x轴数组元素个数
    int[] yv = new int[720];// y轴数组元素个数
    int[] xv1 = new int[720];// x轴数组元素个数
    int[] yv1 = new int[720];// y轴数组元素个数
    public textview tv;
    // screenshot screenshot = new screenshot();
    private int batteryn; // 目前电量
    private int batteryv; // 电池电压
    // private double batteryt; //电池温度
    private string batterystatus; // 电池状态
    private string batterytemp; // 电池使用情况
 
    /** called when the activity is first created. */
    @override
    public void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        getwindow().setflags(windowmanager.layoutparams.flag_keep_screen_on,
                windowmanager.layoutparams.flag_keep_screen_on);
        setcontentview(r.layout.main);
        this.button = (button) this.findviewbyid(r.id.my_button);// 截图按键定义
        // 截图按键监听
        this.button.setonclicklistener(new onclicklistener() {
            public void onclick(view v) {
                simpledateformat sdf = new simpledateformat(
                        "yyyy-mm-dd_hh-mm-ss", locale.us);// 日期格式名定义
 
                string fname = "/sdcard/" + sdf.format(new date()) + ".png";// 存储路径及文件名定义
 
                view view = v.getrootview();
 
                view.setdrawingcacheenabled(true);
 
                view.builddrawingcache();
 
                bitmap bitmap = view.getdrawingcache();
 
                if (bitmap != null) {
                    system.out.println("bitmap got!");
 
                    try {
 
                        fileoutputstream out = new fileoutputstream(fname);
 
                        bitmap.compress(bitmap.compressformat.png, 100, out);// 图片格式及质量输出
 
                        system.out.println("file" + fname + "output done.");
 
                    } catch (exception e) {
 
                        e.printstacktrace();
 
                    }
 
                } else {
                    system.out.println("bitmap is null!");
                }
            }
        });
        // mytag可以随便写,可以写应用名称等
        powermanager pm = (powermanager) getsystemservice(context.power_service);
        // 换成powermanager.screen_dim_wake_lock会变暗)
        powermanager.wakelock wl = pm.newwakelock(
                powermanager.screen_bright_wake_lock, "mytest");
        wl.acquire();// 开启屏幕常亮
 
        tv = (textview) findviewbyid(r.id.tv);// 电池信息打印控件定义
 
        // 注册一个系统 broadcastreceiver,作为访问电池计量之用,这个不能直接在androidmanifest.xml中注册
        registerreceiver(mbatinforeceiver, new intentfilter(
                intent.action_battery_changed));
 
        context = getapplicationcontext();
        context1 = getapplicationcontext();// 图2
        // 这里获得main界面上的布局,下面会把图表画在这个布局里面
        linearlayout layout = (linearlayout) findviewbyid(r.id.linearlayout1);
 
        // 这个类用来放置曲线上的所有点,是一个点的集合,根据这些点画出曲线
        series = new xyseries(title);
        series1 = new xyseries(title);// 图2
        // 创建一个数据集的实例,这个数据集将被用来创建图表
        mdataset = new xymultipleseriesdataset();
        mdataset1 = new xymultipleseriesdataset();
        // 将点集添加到这个数据集中
        mdataset.addseries(series);
        mdataset1.addseries(series1);// 图2
        // 以下都是曲线的样式和属性等等的设置,renderer相当于一个用来给图表做渲染的句柄
        int color = color.green;
        int color1 = color.red;
        pointstyle style = pointstyle.circle;
        renderer = buildrenderer(color, style, true);
        renderer1 = buildrenderer(color1, style, true);// 图2
 
        // 设置好图表的样式(横轴时间分钟值,纵轴电压毫伏值)
        setchartsettings(renderer, "x", "y", 0, 240, 3400, 4400, color.white,
                color.white);
        setchart1settings(renderer1, "x", "y", 0, 240, 0, 100, color.white,
                color.white);
        // 生成图表
        chart = chartfactory.getlinechartview(context, mdataset, renderer);
        chart1 = chartfactory.getlinechartview(context1, mdataset1, renderer1);// 图2
        </span><span style="font-size:12px;">// 将图表添加到布局中去,此处的纵向尺寸设置存在一些问题,当两张图都设置<span style="font-family: arial, helvetica, sans-serif;">wrap_content</span>时,在实际界面上只显示第一张图,在这里可根据手                  // </span><span style="font-family: arial, helvetica, sans-serif;">机屏幕的大小设置具</span><span style="font-family: arial, helvetica, sans-serif;">体的数值(像素点个数),可以保证两张图都能显示在屏幕上
</span><span style="font-size:14px;">        layout.addview(chart, new layoutparams(layoutparams.fill_parent,layoutparams.wrap_content));
        layout.addview(chart1, new layoutparams(layoutparams.fill_parent,layoutparams.wrap_content));
        // layout.addview(chart, new layoutparams(layoutparams.fill_parent,
        // 400));//525
        // layout.addview(chart1, new layoutparams(layoutparams.fill_parent,
        // 400));//图2 525
        // 这里的handler实例将配合下面的timer实例,完成定时更新图表的功能
        handler = new handler() {
            @override
            public void handlemessage(message msg) {
                // 刷新图表
                updatechart();// 电压变化曲线刷新
                updatechart1();// 电量变化曲线刷新
                super.handlemessage(msg);
 
            }
        };
 
        task = new timertask()// 刷新绘图计时任务配置
        {
            @override
            public void run() {
                message message = new message();
                message.what = 1;
                handler.sendmessage(message);
            }
        };
        timer.schedule(task, 0, 60000);// 以一分钟为时间间隔运行
 
        task1 = new timertask()// 保存绘图计时任务配置
        {
            @override
            public void run() {
                if (batterystatus == "充满电"
                        || (batterystatus == "放电状态" && batteryn == 1))// 充/放电完成条件设定
                {
                    button.callonclick();// 保存曲线图按键触发
                    timer.cancel(); // 停止计时功能
                }
            }
        };
        timer.schedule(task1, 0, 10000);// 以十秒钟为时间间隔运行
    }
 
    @override
    public void ondestroy() // 结束程序声明
    {
        button.callonclick();// 保存曲线图按键触发
        // 当结束程序时关掉timer
        timer.cancel();
        // wl.release();
        // wl = null;
        super.ondestroy();
    }
 
    protected xymultipleseriesrenderer buildrenderer(int color,
            pointstyle style, boolean fill)// 配置绘图属性
    {
        xymultipleseriesrenderer renderer = new xymultipleseriesrenderer();
 
        // 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
        xyseriesrenderer r = new xyseriesrenderer();
        r.setcolor(color);
        r.setpointstyle(style);
        r.setfillpoints(fill);
        r.setlinewidth((float) 1);// 线粗尺寸
        renderer.addseriesrenderer(r);
 
        return renderer;
    }
 
    // 图2
    protected xymultipleseriesrenderer buildrenderer1(int color1,
            pointstyle style, boolean fill)// 配置绘图属性
    {
        xymultipleseriesrenderer renderer1 = new xymultipleseriesrenderer();// 图2
        // 设置图表中曲线本身的样式,包括颜色、点的大小以及线的粗细等
        xyseriesrenderer r = new xyseriesrenderer();
        r.setcolor(color1);
        r.setpointstyle(style);
        r.setfillpoints(fill);
        r.setlinewidth((float) 1);// 线粗尺寸
        renderer1.addseriesrenderer(r);
 
        return renderer1;
    }
 
    protected void setchartsettings(xymultipleseriesrenderer renderer,
            string xtitle, string ytitle, double xmin, double xmax,
            double ymin, double ymax, int axescolor, int labelscolor) {
        // 有关对图表的渲染可参看api文档
 
        renderer.setcharttitle(title);
        renderer.setxtitle(xtitle);
        renderer.setytitle(ytitle);
        renderer.setxaxismin(xmin);
        renderer.setxaxismax(xmax);
        renderer.setyaxismin(ymin);
        renderer.setyaxismax(ymax);
        renderer.setaxescolor(axescolor);
        renderer.setlabelscolor(labelscolor);
        renderer.setshowgrid(true);
        renderer.setgridcolor(color.green);// 曲线颜色
        renderer.setxlabels(20);
        renderer.setylabels(10);
        renderer.setcharttitle("时间/电压变化曲线图");// 图表名称
        renderer.setxtitle("时间(min)");// 横坐标名称
        renderer.setytitle("电压(mv)");// 纵坐标名称
        renderer.setylabelsalign(align.right);
        renderer.setpointsize((float) 1.5);// 设置点的大小
        renderer.setshowlegend(false);
        renderer.setpanenabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
        renderer.setzoomenabled(true, false);// 设置缩放,横向可以,纵向不可以
        // renderer.setzoomlimits(new double[] { 0, 720, 3400, 4400 });//设置缩放的范围
        // renderer.setpanlimits(new double[] { -0.5, 720, 3400, 4400
        // });//设置拉动的范围
    }
 
    // 图2
    protected void setchart1settings(xymultipleseriesrenderer renderer1,
            string xtitle, string ytitle, double xmin, double xmax,
            double ymin, double ymax, int axescolor, int labelscolor) {
        // 有关对图表的渲染可参看api文档
 
        renderer1.setcharttitle(title);
        renderer1.setxtitle(xtitle);
        renderer1.setytitle(ytitle);
        renderer1.setxaxismin(xmin);
        renderer1.setxaxismax(xmax);
        renderer1.setyaxismin(ymin);
        renderer1.setyaxismax(ymax);
        renderer1.setaxescolor(axescolor);
        renderer1.setlabelscolor(labelscolor);
        renderer1.setshowgrid(true);
        renderer1.setgridcolor(color.green);// 曲线颜色
        renderer1.setxlabels(20);
        renderer1.setylabels(10);
        renderer1.setcharttitle("时间/电量变化曲线图");// 图表名称
        renderer1.setxtitle("时间(min)");// 横坐标名称
        renderer1.setytitle("电量(%)");// 纵坐标名称
        renderer1.setylabelsalign(align.right);
        renderer1.setpointsize((float) 1.5);// 设置点的大小
        renderer1.setshowlegend(false);
        renderer1.setpanenabled(true, false);// 设置滑动,这边是横向可以滑动,纵向不可滑动
        renderer1.setzoomenabled(true, false);// 设置缩放,横向可以,纵向不可以
        // renderer1.setzoomlimits(new double[] { 0, 720, 0, 100 });//设置缩放的范围
        // renderer1.setpanlimits(new double[] { -0.5, 720, 0, 100 });//设置拉动的范围
    }
 
    private void updatechart()// 更新绘图方法
    {
 
        // 设置好下一个需要增加的节点
        addx = (int) (addx + 1);
        addy = batteryv;
        // 移除数据集中旧的点集
        mdataset.removeseries(series);
        // 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
        int length = series.getitemcount();
        if (length > 720) {
            length = 720;
        }
        // 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
        for (int i = 0; i < length; i++) {
            xv[i] = (int) series.getx(i);
            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();
    }
 
    // 图2
    private void updatechart1()// 更新绘图方法
    {
 
        // 设置好下一个需要增加的节点
        addx1 = (int) (addx1 + 1);
        addy1 = batteryn;
        // 移除数据集中旧的点集
        mdataset1.removeseries(series1);
        // 判断当前点集中到底有多少点,因为屏幕总共只能容纳240个,所以当点数超过240时,长度永远是240
        int length1 = series1.getitemcount();
        if (length1 > 720) {
            length1 = 720;
        }
        // 将旧的点集中x和y的数值取出来放入backup中,并且将x的值加1,造成曲线向右平移的效果
        for (int j = 0; j < length1; j++) {
            xv1[j] = (int) series1.getx(j);
            yv1[j] = (int) series1.gety(j);
        }
        // 点集先清空,为了做成新的点集而准备
        series1.clear();
 
        // 将新产生的点首先加入到点集中,然后在循环体中将坐标变换后的一系列点都重新加入到点集中
        // 这里可以试验一下把顺序颠倒过来是什么效果,即先运行循环体,再添加新产生的点
        series1.add(addx1, addy1);
        for (int l = 0; l < length1; l++) {
            series1.add(xv1[l], yv1[l]);
        }
        // 在数据集中添加新的点集
        mdataset1.addseries(series1);
 
        // 视图更新,没有这一步,曲线不会呈现动态
        // 如果在非ui主线程中,需要调用postinvalidate(),具体参考api
        chart1.invalidate();
    }
 
    /* 创建电池状态广播接收器 */
    public broadcastreceiver mbatinforeceiver = new broadcastreceiver() {
        public void onreceive(context context, intent intent) {
            string action = intent.getaction();
 
            // 如果捕捉到的action是action_battery_changed, 就运行onbatteryinforeceiver()
 
            if (intent.action_battery_changed.equals(action)) {
                batteryn = intent.getintextra("level", 0); // 目前电量
                batteryv = intent.getintextra("voltage", 0); // 电池电压
                // batteryt = intent.getintextra("temperature", 0); //电池温度
 
                switch (intent.getintextra("status",
                        batterymanager.battery_status_unknown)) {
                case batterymanager.battery_status_charging:
                    batterystatus = "充电状态";
                    break;
                case batterymanager.battery_status_discharging:
                    batterystatus = "放电状态";
                    break;
                case batterymanager.battery_status_not_charging:
                    batterystatus = "未充电";
                    break;
                case batterymanager.battery_status_full:
                    batterystatus = "充满电";
 
                    break;
                case batterymanager.battery_status_unknown:
                    batterystatus = "未知道状态";
                    break;
                }
 
                switch (intent.getintextra("health",
                        batterymanager.battery_health_unknown)) {
                case batterymanager.battery_health_unknown:
                    batterytemp = "未知错误";
                    break;
                case batterymanager.battery_health_good:
                    batterytemp = "状态良好";
                    break;
                case batterymanager.battery_health_dead:
                    batterytemp = "电池没有电";
 
                    break;
                case batterymanager.battery_health_over_voltage:
                    batterytemp = "电池电压过高";
                    break;
                case batterymanager.battery_health_overheat:
                    batterytemp = "电池过热";
                    break;
                }
                tv.settext("目前电量为" + batteryn + "% --- " + batterystatus + "\n"
                        + "电压为" + batteryv + "mv ----- " + batterytemp);
 
            }
        }
 
    };
 
    @override
    public boolean onkeydown(int keycode, keyevent event)// 程序按返回键退出处理
    {
        switch (keycode) {
        case keyevent.keycode_back:
            // 双击退出
            // if (isstart == true){isstart = false;}//关闭前确认频闪是否关闭
            if ((system.currenttimemillis() - mexittime) > 2000) {
                toast.maketext(this, "再按一次退出", toast.length_short).show();
                mexittime = system.currenttimemillis();
            } else {
                // isstart = false;
                finish();
            }
            return true;
 
        default:
            break;
        }
        return super.onkeydown(keycode, event);
    }
 
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>  
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/linearlayout1"
    
    android:orientation="vertical"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"
    android:layout_weight="1"
    >  
<!--  -->
<textview  
    android:id = "@+id/tv" 
      
    android:layout_width="fill_parent"  
    android:layout_height="wrap_content" 
    
    />     
<button
  android:text="保存该曲线图"
  android:textsize="4pt"
  android:id="@+id/my_button"
  
  android:layout_width="fill_parent"
  android:layout_height="28dp"
  android:layout_alignbottom="@+id/tv">
  <!--android:layout_alignparentbottom="true"-->
  
</button>
</linearlayout>

androidmanifest.xml配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cfzz.vcd"
    android:versioncode="1"
    android:versionname="1.0"> 
    
    <uses-sdk android:minsdkversion="10" />
    <uses-permission android:name="android.permission.read_frame_buffer"/>
    <uses-permission android:name="android.permission.write_external_storage"/>
    <uses-permission android:name="android.permission.wake_lock" />
 
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity android:name="org.achartengine.graphicalactivity" />
        <activity
            android:name="com.cfzz.vcd.voltagechangedraw"
            android:screenorientation="portrait"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.main" />
 
                <category android:name="android.intent.category.launcher" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>

在该源码中,我们绘制了两条曲线,一条是电压变化曲线,另一条是电量变化曲线,并加一个保存手机屏幕的截图按钮和自动保存时间任务(也可手动保存),用来保存绘制的截图。

运行结果图(充电曲线图):

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。