本篇主要是以Android的graphics.drawable來繪製動態曲線,程式碼如下:
Layout部分:
main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<edu.nkut.sensorgraph.GraphView <--這裡要注意在GraphView 前面要加入程式的Package名稱,否則程式會出錯。
android:id="@+id/graph"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="4" />
<TextView
android:id="@+id/value"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="6"
android:background="#fff"
android:gravity="center"
android:text="@string/app_name"
android:textSize="40sp" />
</LinearLayout>
程式1:(輸入資訊用)
MainActivity.java
package edu.nkut.sensorgraph;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView;
public class MainActivity extends Activity {
private GraphView mGraphView;
TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
mGraphView = (GraphView) findViewById(R.id.graph);
mGraphView.setMaxValue(10); //設定圖形數字最大值
mTextView = (TextView) findViewById(R.id.value);
Thread t = new MyThread(); // 產生Thread物件
t.start();
}
class MyThread extends Thread {
public void run() {
super.run();
try {
do {
java.util.Random rnd = new java.util.Random(
System.currentTimeMillis()); // 取亂數
float mInput = new Float(rnd.nextInt(1000) + 0) / 100; // 取0~10小數兩位亂數值
final float reading = mInput; // mInput偵測到的接收值,本程式使用亂數模擬。
addPoint(reading); // 顯示心跳線
setText(Float.toString((reading))); // 顯示TextView值
sleep(100); // 暫停100ms
} while (MainActivity.MyThread.interrupted() == false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 顯示心跳線
private void addPoint(final float point) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mGraphView.addDataPoint(point);
}
});
}
// 顯示TextView值
private void setText(final String str) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(str);
}
});
}
}
程式2: (繪圖用)
GraphView.java
package edu.nkut.sensorgraph;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class GraphView extends View {
private Bitmap mBitmap;
private Paint mPaint = new Paint();
private Canvas mCanvas = new Canvas();
private float mSpeed = 10.0f; //更改顯示速度(寬窄),數字越小顯示越密;最小設1.0f。
private float mLastX;
private float mScale;
private float mLastValue;
private float mYOffset;
private int mColor;
private float mWidth;
private float maxValue = 1024f;
public GraphView(Context context) {
super(context);
init();
}
public GraphView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mColor = Color.argb(192, 64, 128, 64); //定義顏色ARGB
mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
}
public void addDataPoint(float value) {
final Paint paint = mPaint;
float newX = mLastX + mSpeed;
final float v = mYOffset + value * mScale;
paint.setColor(mColor);
mCanvas.drawLine(mLastX, mLastValue, newX, v, paint);
mLastValue = v;
mLastX += mSpeed;
invalidate();
}
public void setMaxValue(int max) {
maxValue = max;
mScale = -(mYOffset * (1.0f / maxValue));
}
public void setSpeed(float speed) {
mSpeed = speed;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565);
mCanvas.setBitmap(mBitmap);
mCanvas.drawColor(0xFFFFFFFF);
mYOffset = h;
mScale = -(mYOffset * (1.0f / maxValue));
mWidth = w;
mLastX = mWidth;
super.onSizeChanged(w, h, oldw, oldh);
}
@Override
protected void onDraw(Canvas canvas) {
synchronized (this) {
if (mBitmap != null) {
if (mLastX >= mWidth) {
mLastX = 0;
final Canvas cavas = mCanvas;
cavas.drawColor(0xFFFFFFFF);
mPaint.setColor(0xFF777777);
cavas.drawLine(0, mYOffset, mWidth, mYOffset, mPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}
}
}
執行結果:
說明:
1.程式在 MainActivity用亂數產生0~10小數兩位值,直接丟給addPoint()及setText()來顯示圖及數據。
2.如要修改接收值的部分只要更改mInput這個參數即可使用。
3.繪圖部分請參考Android Developers的android.graphics.drawable 說明。
參考:
1.android.graphics.drawable | Android Developers
http://developer.android.com/reference/android/graphics/drawable/package-summary.html
==============延伸閱讀=====================
1.如何在Android上繪出折線圖、條狀圖、圓餅圖、...
http://www.cheng-min-i-taiwan.blogspot.tw/2012/09/android.html
你好
回覆刪除請問要如何畫出負數?
我的需求是-10~10
程式中有設定最大值
不過我找不到設定最小值的方法
還是說只能從0開始?
目前只能提供最大值,你可以自行修改GraphView類別,增加private float minValue 即可。
刪除請教別人後 已解決
刪除以下為方法:
把mScale = -(mYOffset * (1.0f / maxValue));
搬到addDataPoint內
把onSizeChanged內mYOffset 設成h/2 0就會在中間了
丟正的就會在0之上
丟負的就在0之下
很讚!
刪除請問假如我想改成不要亂數,而用sensor的數據來繪出動態線(我是用經過藍芽讀去數據),要如何去更改
回覆刪除將 mInput由原來的亂數改成藍牙所接收的數據。
刪除請問 我已經將 mInput改成 MIT BIH 數據庫裡的數據
回覆刪除經由藍芽傳輸,但發現畫出來的圖跟預期有很大的落差
請問是數據過大造成的嗎?
但如果不經由藍芽傳輸直接讀入TXT檔來話又是很正常的
官方有說取樣頻率360HZ
您好
回覆刪除我現在已經可以將wifi收到的數據即時的顯示在我的GraphView上
請問有什麼方法可以同時顯示兩筆不同的資料?(兩條動態折線)