<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
我們在安卓開發中,有時會用到統計圖表的功能,而曲線繪製是其中比較典型的一種,一般是利用給定的座標點集和安卓自帶的繪圖模組進行繪製,直接得到的是一張完整的靜態的曲線圖。但有時,我們需要動態繪製一些曲線圖,就像我們開啟電腦的工作管理員,裡面有一個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>
在該原始碼中,我們繪製了兩條曲線,一條是電壓變化曲線,另一條是電量變化曲線,並加一個儲存手機螢幕的截圖按鈕和自動儲存時間任務(也可手動儲存),用來儲存繪製的截圖。
執行結果圖(充電曲線圖):
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45