Androidでペインティングキャンバスアプリケーションを開発する場合、すべてのポイントを追跡し、別のキャンバスに再描画する必要があります。これですべてのポイントを追跡できますが、描画と再描画の場合にポイント描画を同期する方法がわかりません。つまり、ユーザーは描画と同じ時間ギャップでポイントを再描画する必要があります。どうすればこれを達成できますか?
1 に答える
これがあなたが探している種類の答えであるかどうかはわかりませんが、私はある種のタイムスタンプ、実際には次のポイントまでの時間差でイベントを記録します。何かのようなもの:
class Point {
int x;
int y;
long deltaTime;
}
タイミングをどれだけ正確にしたいかはあなた次第です。秒からミリ秒の精度で十分です。このポイントが描画されるまでの時間、または次のポイントが描画されるまでの時間のいずれかとして解釈できますdeltaTime
(私の例では後者を使用します)。
直接タイムスタンプの代わりにdeltaTimeを使用するいくつかの理由は、非常に長い一時停止をチェックできるため、再生時にデルタ時間を計算する必要があるためです。また、これをlongとして使用すると、非常に長い一時停止に十分なスペースが得られ、Handler
実行前に待機するミリ秒数の長整数を受け入れるクラスを使用できるようになります。
public class Redrawer implements Handler.callback {
LinkedList<Point> points; //List of point objects describing your drawing
Handler handler = new Handler(this); //Probably should place this in class initialization code
static final int MSG_DRAW_NEXT = 0;
public void begin(){
//Do any prep work here and then we can cheat and mimic a message call
//Without a delay specified it will be called ASAP but on another
//thread
handler.sendEmptyMessage(MSG_DRAW_NEXT);
}
public boolean handleMessage(Message msg){
//If you use the handler for other things you will want to
//branch off depending on msg.what
Point p = points.remove(); //returns the first element, and removes it from the list
drawPoint(p);
if (!points.isEmpty())
handler.sendEmptyMessageDelayed(MSG_DRAW_NEXT, p.deltaTime);
public void drawPoint(Point p){
//Canvas drawing code here
//something like canvas.drawPixel(p.x, p.y, SOMECOLOR);
//too lazy to look up the details right now
//also since this is called on another thread you might want to use
//view.postInvalidate
}
このコードは、完全または防弾にはほど遠いです。つまり、ユーザーがアクティビティを切り替えたり、電話を受けたりしたために、後で再描画を一時停止または再開する必要があります。また、キャンバスオブジェクトを取得する場所や方法の詳細も実装していません(その部分は今では下がっています)。View.postInvalidate
また、画面の小さな部分を再描画する方がすべてを再描画するよりもはるかに高速であるため、送信先の長方形を作成できるように、前のポイントを追跡することもできます。最後に、クリーンアップを実装しませんでした。必要に応じて、ハンドラーとポイントのリストを破棄する必要があります。
これにはおそらくいくつかの異なるアプローチがあり、いくつかはおそらくこれよりも優れています。タッチイベント間の長い一時停止が心配な場合はdeltaTime
、たとえば10秒を超えるかどうかのチェックを追加してから、10秒に上書きします。元。handler.sendEmptyMessage(MSG_DRAW_NEXT, Math.min(p.deltaTime, 100000));
ただし、ハードコードされた数値の代わりに定数を使用することをお勧めします。
お役に立てれば