2012-01-16 7 views
3

私はLunarLanderの例をベースとして画面を移動するシェイプを描画しようとしています。問題は、 '移動'の代わりに新しい位置に再描画するだけで、古い位置も引き続き描画されるということです。問題を示すためにできる最短のコードをまとめました。Android - カスタムSurfaceViewを使用して動くシェイプをアニメーション化する方法は?

主な活動:

package ybz.test; 

import ybz.fireworks.R; 
import android.app.Activity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.view.View.OnClickListener; 

public class TestActivity extends Activity implements OnClickListener { 

    private static final String TAG = "CL_FireworksActivity"; 
    MySurfaceView mySurfaceView; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     try { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.main); 

      findViewById(R.id.btnStart).setOnClickListener(this); 
      findViewById(R.id.btnStop).setOnClickListener(this); 

      mySurfaceView = (MySurfaceView) (findViewById(R.id.surfaceView1)); 
     } catch (Exception e) { 
      Log.d(TAG, "Failed to create; " + e.getMessage()); 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void onClick(View v) { 
     switch (v.getId()) { 
     case R.id.btnStart: 
      try { 
       mySurfaceView.startThread(); 
      } catch (Exception e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      break; 
     case R.id.btnStop: 
      mySurfaceView.stopThread(); 
      break; 
     } 
    } 
} 

カスタムSurfaceView:

package ybz.test; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Point; 
import android.graphics.Paint.Cap; 
import android.graphics.Paint.Style; 
import android.util.AttributeSet; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MySurfaceView extends SurfaceView implements 
     SurfaceHolder.Callback { 
    private DrawThread drawThread; 
    private Paint paint = new Paint(); 
    private Point location; 

    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); 
     setFocusable(true); 
     paint.setColor(Color.BLUE); 
     paint.setStrokeWidth(1); 
     paint.setAntiAlias(true); 
     paint.setStrokeCap(Cap.SQUARE); 
     paint.setStyle(Style.FILL); 
     location = new Point(0, 200); 
    } 

    public void startThread() { 
     drawThread = new DrawThread(getHolder(), this); 
     drawThread.setRunning(true); 
     drawThread.start(); 
    } 

    public void stopThread() { 
     drawThread.setRunning(false); 
     drawThread.stop(); 
    } 

    public void update() { 
     location.x = location.x + 10; 
     if(location.x > getWidth()) { 
      location.x = 0; 
     } 
    } 

    public void onDraw(Canvas canvas) { 
     canvas.drawCircle(location.x, location.y, 15, paint); 
    } 

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

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

     public void setRunning(boolean run) { 
      this.run = run; 
     } 

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

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     // TODO Auto-generated method stub 
    } 

} 

レイアウト:

<?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" > 

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

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

     <Button 
      android:id="@+id/btnStart" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_margin="5dp" 
      android:text="@string/lbl_start" /> 

     <Button 
      android:id="@+id/btnStop" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_margin="5dp" 
      android:text="@string/lbl_stop" /> 

    </LinearLayout> 

</LinearLayout> 

答えて

3

どうやら表面図は、各ドローの後に自分自身をクリアしていないので、私は何をする必要がありますそれは明白です。 Android developer guideから 引用:

注:それぞれがあなたがSurfaceHolderからキャンバスを取得するパスで、キャンバスの 以前の状態が保持されます。グラフィックをアニメーション化するには、適切に を実行するには、サーフェス全体を再ペイントする必要があります。 の例では、 にdrawColor()を入力するか、 drawBitmap()で背景イメージを設定することでCanvasの以前の状態を消去できます。それ以外の場合は、以前に実行した図面の痕跡が表示されます。

onDraw()メソッドが更新されます。

public void onDraw(Canvas canvas) { 
    canvas.drawColor(Color.BLACK); 
    canvas.drawCircle(location.x, location.y, 15, paint); 
} 
+1

'canvas.drawColor(0、PorterDuff.Mode.CLEAR)を用いた表面ビューのキャンバスをクリアする方法はあり;'前に、このリンクながら –

-1

あなたはSurfaceView派生クラスのonDraw()メソッドの開始時に背景色でキャンバスを再描画する必要があります。

ここに、Androidグラフィック&アニメーションを完全に理解するのに役立つ3つのビデオチュートリアルがあります。ノーマルビューとサーフェスビューの両方を使用してアニメーションを開発する方法について説明します。

https://youtu.be/kRqsoApOr9U

https://youtu.be/Ji84HJ85FIQ

https://youtu.be/U8igPoyrUf8

+0

を描きます質問に答えるかもしれないが、答えの本質的な部分をここに含めて、参考のためのリンクを提供する方がよい。リンクされたページが変更された場合、リンクのみの回答は無効になります。 - [レビューより](/レビュー/低品質の投稿/ 16142504) –

+0

編集されました...回答の必須部分が追加されました... –

関連する問題