【发布时间】:2015-06-11 01:38:09
【问题描述】:
我有一个简单的应用程序,它通过嵌套在活动布局中的 SurfaceView 在屏幕上显示图像。
我有一个 SurfaceViewExample 类,它创建 OurView 的新实例,并包含按钮调用的方法。共有三种方法:
- 第一个方法是arrowPressed(View view),当三个箭头键中的任何一个被按下时调用。它获取调用它的按钮的 id 并将其传递给
- arrowAction(OurView ourview, String direction) 调用
-
moveImage(int xChange, int yChange) 以及沿该方向移动图像所需的 x 和 y 变化。
public void arrowPressed(View view) { switch (view.getId()) { case R.id.arrowLeft: arrowAction(gameView, "left"); break; case R.id.arrowRight: arrowAction(gameView, "right"); break; case R.id.arrowUp: arrowAction(gameView, "up"); break; } } ------------------------------------------------------------------------------------ void arrowAction(OurView ourView, String direction) { switch (direction) { case "left": ourView.moveImage(-1,0); break; case "right": ourView.moveImage(1,0); break; case "up": ourView.moveImage(0,1); break; } } ------------------------------------------------------------------------------------ void moveImage(int xChange, int yChange) { xCoord = xCoord + xChange; yCoord = yCoord + yChange; }
这一切似乎都按预期工作。 moveImage 被成功调用,它修改了 xCoord 和 yCoord 变量。当我从 moveImage 中打印 x 和 y 坐标时,它们反映了它们更改的值。但是,moveImage 中的 xCoord 和 yCoord 与线程 MyThread 中的 xCoord 和 yCoord 之间似乎存在脱节。
doDraw(Canvas canvas) 方法在 (xPos, yPos) 处绘制位图(这些变量只是调整了 x 和 y 坐标,以便图像以该坐标点为中心,而不是让它的左上角在那坐标点)。当我通过这种方法打印 x 和 y 坐标时,它们会反映原始值。
public void doDraw(Canvas canvas) {
xPos = xCoord - (testimg.getWidth()/2);
yPos = yCoord - (testimg.getHeight()/2);
canvas.drawBitmap(testimg, xPos, yPos, null);
}
我能想到发生这种情况的唯一原因是 moveImage 正在创建名为 xCoord 和 yCoord 的新局部变量。但是这没有意义,因为它成功地获取了 xCoord 和 yCoord 的原始值。
完整代码:
SurfaceView 示例:
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class SurfaceViewExample extends Activity {
OurView gameView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new OurView(this);
setContentView(R.layout.activity_surface_view_example);
}
public void arrowPressed(View view) {
switch (view.getId()) {
case R.id.arrowLeft:
arrowAction(gameView, "left");
break;
case R.id.arrowRight:
arrowAction(gameView, "right");
break;
case R.id.arrowUp:
arrowAction(gameView, "up");
break;
}
}
void arrowAction(OurView ourView, String direction) {
switch (direction) {
case "left":
ourView.moveImage(-1,0);
break;
case "right":
ourView.moveImage(1,0);
break;
case "up":
ourView.moveImage(0,1);
break;
}
}
}
我们的观点:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class OurView extends SurfaceView implements SurfaceHolder.Callback {
private MyThread myThread;
private SurfaceHolder holder;
private Bitmap testimg;
public int xCoord = 500;
public int yCoord = 500;
int xPos;
int yPos;
public OurView(Context context) {
super(context);
init();
}
public OurView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public OurView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
myThread = new MyThread(this);
holder = getHolder();
holder.addCallback(this);
testimg = BitmapFactory.decodeResource(getResources(),R.drawable.testimg);
}
void moveImage(int xChange, int yChange) {
xCoord = xCoord + xChange;
yCoord = yCoord + yChange;
System.out.println("-----");
System.out.println("-----");
System.out.println(xCoord);
System.out.println(yCoord);
System.out.println("-----");
System.out.println("-----");
}
public void doDraw(Canvas canvas) {
System.out.println("Starting drawing...");
System.out.println(xCoord);
System.out.println(yCoord);
xPos = xCoord - (testimg.getWidth()/2);
yPos = yCoord - (testimg.getHeight()/2);
System.out.println(xPos);
System.out.println(yPos);
canvas.drawBitmap(testimg, xPos, yPos, null);
System.out.println("Drawing finished.");
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
myThread.setRunning(true);
myThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
}
catch (InterruptedException e) {}
}
}
}
我的线程:
import android.graphics.Canvas;
public class MyThread extends Thread{
OurView myView;
private boolean running = false;
public MyThread(OurView view) {
myView = view;
}
public void setRunning(boolean run) {
running = run;
}
@Override
public void run() {
while(running){
Canvas canvas = myView.getHolder().lockCanvas();
if(canvas != null){
synchronized (myView.getHolder()) {
myView.doDraw(canvas);
}
myView.getHolder().unlockCanvasAndPost(canvas);
}
try {
sleep(30);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
MyThread 类几乎是来自Create animation on SurfaceView in background Thread 的纯复制+粘贴。
【问题讨论】:
标签: java android multithreading canvas scope