[UPDATE] この質問を終えるには、次の2つの方法でグラフを実装しました(下記参照)。 drawCurve()
はCanvas
とfloat
の配列を受け取ります。配列は適切に埋められます(タイムスタンプは配列の値インデックスによって想定されます)、0.0から1.0まで変化します。アレイはwindowStart
のwindowSize
値の配列のチャンクを循環的に取りますprepareWindowArray()
に送信されます。Androidのカスタム動的グラフ
GraphViewとデータプロバイダ(Bluetoothデバイス)が使用する配列は同じです。中央のクラスは、GraphViewがBluetoothデバイスによって書き込まれているデータを読み取っていないことを保証します。 GraphViewは常に配列をループし、繰り返しごとにそれを再描画するので、Bluetoothデバイスによって書き込まれたデータに従って更新され、Bluetoothデバイスの書き込み頻度をグラフのリフレッシュ頻度に強制することによって、私の信号のアニメーション。
GraphView
のinvalidate()
方法は、すべてのx
ミリ秒でグラフを更新するにはTimer
を実行Activity
、によって呼び出されます。グラフがリフレッシュされる頻度は動的に設定され、Bluetoothデバイス(パケットのヘッダーにある信号の周波数を指定する)からのデータの流れに適応します。
私のGraphView
の完全なコードは、私が以下に書いた答え(答えのセクションにあります)にあります。あなたがエラーを見つけたり、それを最適化する方法を見つけたら、教えてください。大いに感謝しています!
/**
* Read a buffer array of size greater than "windowSize" and create a window array out of it.
* A curve is then drawn from this array using "windowSize" points, from left
* to right.
* @param canvas is a Canvas object on which the curve will be drawn. Ensure the canvas is the
* later drawn object at its position or you will not see your curve.
* @param data is a float array of length > windowSize. The floats must range between 0.0 and 1.0.
* A value of 0.0 will be drawn at the bottom of the graph, while a value of 1.0 will be drawn at
* the top of the graph. The range is not tested, so you must ensure to pass proper values, or your
* graph will look terrible.
* 0.0 : draw at the bottom of the graph
* 0.5 : draw in the middle of the graph
* 1.0 : draw at the top of the graph
*/
private void drawCurve(Canvas canvas, float[] data){
// Create a reference value to determine the stepping between each points to be drawn
float incrementX = (mRightSide-mLeftSide)/(float) windowSize;
float incrementY = (mBottomSide - mTopSide);
// Prepare the array for the graph
float[] source = prepareWindowArray(data);
// Prepare the curve Path
curve = new Path();
// Move at the first point.
curve.moveTo(mLeftSide, source[0]*incrementY);
// Draw the remaining points of the curve
for(int i = 1; i < windowSize; i++){
curve.lineTo(mLeftSide + (i*incrementX), source[i] * incrementY);
}
canvas.drawPath(curve, curvePaint);
}
アレイの円形の動作を実装prepareWindowArray()
方法
/**
* Extract a window array from the data array, and reposition the windowStart
* index for next iteration
* @param data the array of data from which we get the window
* @return an array of float that represent the window
*/
private float[] prepareWindowArray(float[] data){
// Prepare the source array for the graph.
float[] source = new float[windowSize];
// Copy the window from the data array into the source array
for(int i = 0; i < windowSize; i++){
if(windowStart+i < data.length) // If the windows holds within the data array
source[i] = data[windowStart + i]; // Simply copy the value in the source array
else{ // If the window goes beyond the data array
source[i] = data[(windowStart + 1)%data.length]; // Loop at the beginning of the data array and copy from there
}
}
// Reposition the buffer index
windowStart = windowStart + windowSize;
// If the index is beyond the end of the array
if(windowStart >= data.length){
windowStart = windowStart % data.length;
}
return source;
}
[/ UPDATE]
私がBluetoothデバイスからデータを読み取るアプリケーションを作っています固定金利。新しいデータがあるたびに、グラフを右側のグラフにプロットし、グラフの残りの部分をリアルタイムで左側に変換します。基本的には、オシロスコープのようになります。
私はカスタムのビューを作成しました。xy軸、タイトルと単位を使用しました。これを行うために、私は単にViewキャンバスにそれらのものを描画します。今私は曲線を描きたい。私は、このメソッドを使用して、既に塗りつぶされた配列から静的なカーブを描くことができます:
public void drawCurve(Canvas canvas){
int left = getPaddingLeft();
int bottom = getHeight()-getPaddingTop();
int middle = (bottom-10)/2 - 10;
curvePaint = new Paint();
curvePaint.setColor(Color.GREEN);
curvePaint.setStrokeWidth(1f);
curvePaint.setDither(true);
curvePaint.setStyle(Paint.Style.STROKE);
curvePaint.setStrokeJoin(Paint.Join.ROUND);
curvePaint.setStrokeCap(Paint.Cap.ROUND);
curvePaint.setPathEffect(new CornerPathEffect(10));
curvePaint.setAntiAlias(true);
mCurve = new Path();
mCurve.moveTo(left, middle);
for(int i = 0; i < mData[0].length; i++)
mCurve.lineTo(left + ((float)mData[0][i] * 5), middle-((float)mData[1][i] * 20));
canvas.drawPath(mCurve, curvePaint);
}
これは私のようなものです。
はまだ(サブ軸が適切にスケーリングされていない)私のグラフ上に定着させるものがありますが、これらは、私は後で修正することができます詳細です。
ここでは、40msごとに曲線を再描画し、古いデータを左側にプッシュし、新しいデータを右側にプロットする動的なもので、この静的グラフ(値の非動的な値を受け取る)を変更し、私は、Bluetoothデバイスによって提供される情報をリアルタイムで視覚化することができました。
既に存在するグラフパッケージがあることは知っていますが、私はこれらのことにちょっと驚いています。私はこのグラフを自分で実装したいと思っています。また、カーブ部分を除いて、私のGraphViewクラスのほとんどが実行されます。
2番目の質問では、グラフに新しい値をどのように送るべきかと思います。私はFIFOスタックのようなものを使うべきですか、単純な倍数の倍数で私が望むものを達成することはできますか?
サイドノートでは、下部の4つのフィールドが既に動的に更新されています。まあ、彼らは "ダイナミック"を偽っているのですが、同じダブル・マトリスを何度も繰り返すので、実際には新鮮な価値を取りません。
ありがとうございました!質問に不明な点がある場合はお知らせください。詳細を更新します。
すべてのプロジェクトにリンクを付けることはできますか?この見て非常に興味深い! –