2012-01-16 93 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()填充 的一種顏色或使用012Bxmap( )設置背景圖像來清除畫布的以前狀態。否則,您將看到之前執行的圖紙的痕跡。

的的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)的表面視圖畫布;'之前繪製 – 2016-05-20 09:41:14

-1

您需要在SurfaceView派生類的onDraw()方法的開始重繪與背景顏色畫布。

這裏是我的三個視頻教程,這將有助於您完全理解Android圖形&動畫。它解釋瞭如何使用普通視圖和表面視圖來開發動畫。

https://youtu.be/kRqsoApOr9U

https://youtu.be/Ji84HJ85FIQ

https://youtu.be/U8igPoyrUf8

+0

雖然這種鏈接可以回答這個問題,最好在這裏包含答案的重要部分,並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/ review/low-quality-posts/16142504) – 2017-05-16 18:01:44

+0

已編輯...添加了答案的重要部分... – 2017-05-16 22:07:34