我正在尝试使用LunarLander示例作为基础绘制将在屏幕上移动的形状。问题是,不是“移动”它们只是在新位置重绘,而旧位置仍然被绘制。我把最短的代码放在一起来证明这个问题。
主要活动:
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>
答案 0 :(得分:3)
显然,每次绘制后Surface视图都不会自行清除,所以我需要明确地进行。 来自Android developer guide的引用:
注意:在每次传递中,您都可以从SurfaceHolder中检索Canvas 将保留以前的画布状态。为了正确 为图形添加动画效果,必须重新绘制整个曲面。对于 例如,您可以通过填写来清除画布的先前状态 使用drawColor()或使用设置背景图像的颜色 drawBitmap()。否则,您将看到图纸的痕迹 以前表演过。
onDraw()方法已更新:
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawCircle(location.x, location.y, 15, paint);
}
答案 1 :(得分:-1)
您需要在SurfaceView派生类的onDraw()方法的开头用背景颜色重绘画布。
以下是我的三个视频教程,可帮助您了解Android Graphics&amp;动画完全。它解释了如何使用普通视图和表面视图开发动画。