2011-09-28 78 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)點應該是視圖的左上角。無論何時應用翻譯/縮放等,您都可能會改變(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

你計算好用於測量角度分鐘手 旋轉相應的模擬象限時鐘...在這裏有點 位的變化可以讓分鐘或小時手在 的觸摸位置旋轉...調用下面的方法在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; 
} 

我有這種方法與作爲計算的角度向量的概念,但如果不是你的代碼多一點,如果ü想我會給這個邏輯....