2011-12-08 38 views
1

我想旋轉屏幕上的2個圓圈。按下按鈕時,一個圓圈順時針旋轉,其他圓圈逆時針旋轉。兩者將旋轉90度,然後停止,直到下一個按鈕單擊。
它的工作,但它看起來非常糟糕。而不是同時旋轉,第一個圓圈旋轉,然後是第二個圓圈。
我讀了關於動畫,但我發現的所有例子展示瞭如何旋轉整個畫布。可能我沒有在正確的位置尋找,並且有辦法以某種方式將動畫分配給對象。
我在下面添加了我的代碼。我很抱歉它不是一個真正的SSCCE,但當我的自定義SurfaceView是主要活動下的內部類時,我得到了錯誤。
Android - 如何旋轉多個2D圖形對象

任何意見或如何正確地做到這一點非常感謝。 活動

package sscce.android.rotation; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 

public class SscceRotationActivity extends Activity implements OnClickListener { 

    private MySurfaceView mySurfaceView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     findViewById(R.id.btnClockwise).setOnClickListener(this); 
     findViewById(R.id.btnCounterClockwise).setOnClickListener(this); 
     mySurfaceView = (MySurfaceView) (findViewById(R.id.surfaceView1)); 
    } 

    public void onClick(View arg0) { 

     switch (arg0.getId()) { 
     case R.id.btnClockwise: 
      mySurfaceView.rotate(true); 
      break; 
     case R.id.btnCounterClockwise: 
      mySurfaceView.rotate(false); 
      break; 
     } 
    } 
} 

自定義SurfaceView

package sscce.android.rotation; 

import android.content.Context; 
import android.content.DialogInterface; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Rect; 
import android.graphics.RectF; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MySurfaceView extends SurfaceView implements 
     SurfaceHolder.Callback { 

    private Circle circle1; 
    private Circle circle2; 
    private DrawThread drawThread; 

    public MySurfaceView(Context context) { 
     super(context); 
     initialize(); 
    } 

    public MySurfaceView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initialize(); 
    } 

    public MySurfaceView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     initialize(); 
    } 

    private void initialize() { 
     getHolder().addCallback(this); 
     drawThread = new DrawThread(getHolder(), this); 
     setFocusable(true); 
    } 

    public void surfaceCreated(SurfaceHolder holder) { 
     circle1 = new Circle(getWidth()/2, getHeight()/2, 50); 
     circle2 = new Circle(getWidth()/2, getHeight()/2, 80); 
     drawThread.setRunning(true); 
     drawThread.start(); 
    } 

    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
     // TODO Auto-generated method stub 
    } 

    public void surfaceDestroyed(SurfaceHolder arg0) { 
     boolean retry = true; 
     drawThread.setRunning(false); 
     while (retry) { 
      try { 
       drawThread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // we will try it again and again... 
      } 
     } 
    } 

    public void onDraw(Canvas canvas) { 
     circle2.onDraw(canvas); 
     circle1.onDraw(canvas); 
    } 

    public void rotate(boolean clockWise) { 
     Rotator rotator1 = new Rotator(circle1, clockWise); 
     Rotator rotator2 = new Rotator(circle2, !clockWise); 
     rotator1.run(); 
     rotator2.run(); 
    } 

    private class Circle { 
     private RectF rectF; 
     private int rotationAngle = 0; 

     MyPaint bluePaint = new MyPaint(1, Paint.Cap.SQUARE, Paint.Style.FILL, 
       Color.BLUE); 
     MyPaint redPaint = new MyPaint(1, Paint.Cap.SQUARE, Paint.Style.FILL, 
       Color.RED); 
     MyPaint yellowPaint = new MyPaint(1, Paint.Cap.SQUARE, 
       Paint.Style.FILL, Color.YELLOW); 
     MyPaint greenPaint = new MyPaint(1, Paint.Cap.SQUARE, Paint.Style.FILL, 
       Color.GREEN); 
     MyPaint borderPaint = new MyPaint(3, Paint.Cap.SQUARE, 
       Paint.Style.STROKE, Color.WHITE); 

     public Circle(int centerX, int centerY, int radius) { 
      rectF = new RectF(new Rect(centerX - radius, centerY - radius, 
        centerX + radius, centerY + radius)); 
     } 

     public void rotateClockwise() { 
      for (int i = 0; i < 90; i++) { 
       rotationAngle++; 
       if (rotationAngle == 360) { 
        rotationAngle = 0; 
        return; 
       } 
       try { 
        Thread.sleep(20, 0); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 

     public void rotateCounterClockwise() { 
      for (int i = 0; i < 90; i++) { 
       rotationAngle--; 
       if (rotationAngle == 0) { 
        rotationAngle = 360; 
        return; 
       } 
       try { 
        Thread.sleep(20, 0); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 

     public void onDraw(Canvas canvas) { 
      canvas.drawArc(rectF, (0 + rotationAngle) % 360, 90, true, 
        bluePaint); 
      canvas.drawArc(rectF, (90 + rotationAngle) % 360, 90, true, 
        redPaint); 
      canvas.drawArc(rectF, (180 + rotationAngle) % 360, 90, true, 
        yellowPaint); 
      canvas.drawArc(rectF, (270 + rotationAngle) % 360, 90, true, 
        greenPaint); 
      canvas.drawArc(rectF, 0, 360, true, borderPaint); 
     } 

     private class MyPaint extends Paint { 
      public MyPaint(int strokeWidth, Paint.Cap cap, Paint.Style style, 
        int color) { 
       setStrokeWidth(strokeWidth); 
       setAntiAlias(true); 
       setStrokeCap(cap); 
       setStyle(style); 
       setColor(color); 
      } 
     } 
    } 

    private class Rotator extends Thread { 
     private Circle circle; 
     private boolean clockwise; 

     public Rotator(Circle circle, boolean clockwise) { 
      this.circle = circle; 
      this.clockwise = clockwise; 
     } 

     @Override 
     public void run() { 
      if (clockwise) { 
       circle.rotateClockwise(); 
      } else { 
       circle.rotateCounterClockwise(); 
      } 
     } 
    } 

    private class DrawThread extends Thread { 
     private SurfaceHolder surfaceHolder; 
     private MySurfaceView surfaceView; 
     private boolean run = false; 

     public DrawThread(SurfaceHolder surfaceHolder, MySurfaceView surfaceView) { 
      this.surfaceHolder = surfaceHolder; 
      this.surfaceView = surfaceView; 
      run = false; 
     } 

     public void setRunning(boolean run) { 
      Log.d("[email protected]", "Run status is " + run); 
      this.run = run; 
     } 

     @Override 
     public void run() { 
      Canvas canvas = null; 
      while (run) { 
       try { 
        canvas = surfaceHolder.lockCanvas(null); 
        synchronized (surfaceHolder) { 
         surfaceView.onDraw(canvas); 
        } 
       } finally { 
        if (canvas != null) { 
         surfaceHolder.unlockCanvasAndPost(canvas); 
        } 
       } 
      } 
     } 
    } 
} 

佈局

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 

    <sscce.android.rotation.MySurfaceView 
     android:id="@+id/surfaceView1" 
     android:layout_width="fill_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" /> 

    <LinearLayout 
     android:id="@+id/linearLayout1" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:gravity="center" > 

     <Button 
      android:id="@+id/btnClockwise" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Clockwise" /> 

     <Button 
      android:id="@+id/btnCounterClockwise" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="Counter Clockwise" /> 
    </LinearLayout> 

</LinearLayout> 

回答

1

你將有更多的成功,如果您更換rotator1/2.run()線,rotator1/2.啓動()

+0

謝謝,解決了它。 – Yoav

2

我想提醒一個不同的方法來使用matrices.The代碼旋轉看起來像

canvas.save(Canvas.MATRIX_SAVE_FLAG); 
canvas.rotate(cwRotation); 
//draw first circle here 
canvas.restore(); 
canvas.save(Canvas.MATRIX_SAVE_FLAG); 
canvas.rotate(ccwRotation); 
//draw second circle here 
canvas.restore(); 

這種方法的優點是非常簡單,不需要額外的類和API,它與OpenGL所做的相似。

+0

這應該進入在MySurfaceView中的onDraw方法? – Yoav

+0

@Yoav無論是,或者你可以在你的Circle的onDraw方法內進行保存/旋轉/繪製/恢復 – kostja