2011-09-28 5 views
5

私は時計の分針を回転させることができる簡単な概念証明アプリを書こうとしています。私はOnTouchEventの正しいロジックを考え出すのに苦労しています。Androidクロックで手を動かす

これまでのところ、私は次のコードを持っている:

public boolean onTouchEvent(MotionEvent e) { 

     float x = e.getX(); 
     float y = e.getY(); 

    switch (e.getAction()) { 
    case MotionEvent.ACTION_MOVE: 
     //find an approximate angle between them. 

     float dx = x-cx; 
     float dy = y-cy; 
     double a=Math.atan2(dy,dx); 

     this.degree = Math.toDegrees(a); 
     this.invalidate(); 
    } 
    return true; 
    } 


protected void onDraw(Canvas canvas) { 
    super .onDraw(canvas); 

    boolean changed = mChanged; 
    if (changed) { 
     mChanged = false; 
    } 

    int availableWidth = getRight() - getLeft(); 
    int availableHeight = getBottom() - getTop(); 

    int x = availableWidth/2; 
    int y = availableHeight/2; 

    cx = x; 
    cy = y; 

    final Drawable dial = mDial; 

    int w = dial.getIntrinsicWidth() + 100; 
    int h = dial.getIntrinsicHeight() + 100; 

    boolean scaled = false; 

    if (availableWidth < w || availableHeight < h) { 
     scaled = true; 

     float scale = Math.min((float) availableWidth/(float) w, (float) availableHeight/(float) h); 

     canvas.save(); 
     canvas.scale(scale, scale, x, y); 
    } 

    if (changed) 
    { 
     dial.setBounds(x - (w/2), y - (h/2), x + (w/2), y + (h/2)); 
    } 

    dial.draw(canvas); 

    canvas.save(); 
    float hour = mHour/12.0f * 360.0f; 

    canvas.rotate(hour, x, y); 

    final Drawable hourHand = mHourHand; 

    if (changed) { 

     w = hourHand.getIntrinsicWidth() + 30; 
     h = hourHand.getIntrinsicHeight() + 30; 

     hourHand.setBounds(x - (w/2), y - (h/2), x + (w/2), y + (h/2)); 
    } 

    hourHand.draw(canvas); 
    canvas.restore(); 

    canvas.save(); 
    float minute = mMinutes/60.0f * 360.0f; 

    if (bearing == 0) 
    { 
     canvas.rotate(minute, x, y); 
    } 
    else 
    { 
     canvas.rotate((float)bearing, x, y); 
    } 

    final Drawable minuteHand = mMinuteHand; 

    if (changed) { 

     w = minuteHand.getIntrinsicWidth() + 30; 
     h = minuteHand.getIntrinsicHeight() + 30; 

     minuteHand.setBounds(x - w, y - h, x + w, y + h); 
    } 

    minuteHand.draw(canvas); 
    canvas.restore(); 

    if (scaled) { 
     canvas.restore(); 
    } 
} 

は次にそれに基づいて、私のOnDrawメソッドは、指定された「this.degree」(ちょうどcanvas.rotateを呼び出す)に分針を回転させます。私は数学がここにいると仮定しています。私はここの例に従うことを試みた:Calculate angle for rotation in Pie Chart、しかしそれは分針を正しく回転させていない。どんな助けもありがとう。

答えて

2

数値が正しく表示されます。あなたの計算は、タッチイベントの角度を与える必要があります。そこでは、中心点の正確な位置にタッチすると0度になるはずです。

  • に気を付けるべきいくつかの事柄は、あなたが正しい方向に回転していることを確認します。これをまっすぐに保つのは難しいので、簡単に締めてください。
  • 値0は、分針が右を指している必要があることを考慮していることを確認してください。たとえば、上向きの分針で始める場合は、計算結果に90度の加算/減算をする必要があります(回転方向に応じて、どちらが正しいかわからない)
  • (cx、cy)が角度を計算したい中心点であることを確認してください
  • 回転するときは、3 arg Canvas.rotate(float, float, float)メソッドを使用するか、別の翻訳を別途追加する必要があります正しい点を中心に回転しています。 回転は常に「現在」(0,0)の点を中心に行われます、変換されず、それが(ビューの左上隅)の回転に

より(0,0)の周りに回転します。 「現在」とは、現在の行列が適用された後の(0,0)点を意味します。最初にonDrawと入力すると、(0,0)点はビューの左上隅になります。翻訳/スケーリング/ etcを適用するたびに、(0,0)点がビューに対して相対的に変更される可能性があります。

私は次のようなものは、回転の正しい中央の設定に関しては、動作するはずだと思う:

//first we save the initial matrix, so we can easily get 
//back to this state after we're done rotating 
canvas.save(); 
//I *think* you need to negate the center offsets here, 
//because you are conceptually moving the canvas, rather 
//than moving the center directly 
canvas.translate(-cx, -cy); 
//<perform the rotation and draw the clock hand> 
//... 

//and now restore the matrix back to the initial state 
canvas.restore(); 
+0

ありがとうございました。私は私の中心点を再確認します。私は、中心点が時計ではなく画面全体に関連しているということが問題だと思います。 240,240のようなものです。それが本当の問題かもしれません。思考? – bek

+0

@ user968322ローテーションの中心に関する追加の詳細をいくつか追加しました。 – JesusFreke

+0

はすべて試しましたが、まだ運がありません。それはランダムな方向に移動を開始します。私のポストの元のコードを更新しました。 – bek

0

あなたの計算は に分針のための角度を測定するための良いアナログに対応する象限に回転させます時計...ここで少し ビットの変更は、 タッチ位置で回転する分または時針を作ることができます....アクションmoveのonTouch()メソッドの下のメソッドを呼び出す

public float getRotationAngle(float x, float y) { 
     float dx = x - cx; 
     float dy = y - cy; 
     double a = Math.atan2(dy, dx); 

     double degree = Math.toDegrees(a)+90; 
     if(angle<0){ 
      degree=degree+360; 
     } 
     return (float) degree; 
} 

コンセプトは角度を計算するためのベクターが、uがしたい場合は、あなたのコードよりも少し多くの場合は、私はそのロジックを与えるよう私はこのアプローチを持っている....

関連する問題