触摸屏时应用程序崩溃
Posted
技术标签:
【中文标题】触摸屏时应用程序崩溃【英文标题】:Application crashes upon touching screen 【发布时间】:2021-08-03 10:18:20 【问题描述】:所以我正在制作一个简单的寻宝游戏。我已经实现了 SurfaceHolder.Callback 和 OnTouchListener 方法。触摸屏幕挖宝时应用崩溃。
这是 DrawSurface 类的代码:
public class DrawSurface extends SurfaceView implements SurfaceHolder.Callback, View.OnTouchListener
private static ArrayList<Item> mInventory;
private final Rect mFieldDim = new Rect();
private ArrayList<Item> mItems;
private ArrayList<PointF> dugHoles;
private Bitmap mBMPField;
private Bitmap mBMPHole;
private SurfaceHolder mHolder;
private MotionEvent motionEvent;
public DrawSurface(Context context, AttributeSet attrs)
super(context, attrs);
init();
public static ArrayList<Item> getInventory()
return mInventory;
public void init()
getHolder().addCallback(this);
setOnTouchListener(this);
mItems = loadItems();
dugHoles = new ArrayList<PointF>();
mBMPField = BitmapFactory.decodeResource(getResources(), R.drawable.field);
mBMPHole = BitmapFactory.decodeResource(getResources(), R.drawable.hole);
mInventory = new ArrayList<Item>();
public void surfaceCreated(SurfaceHolder surfaceHolder)
mHolder = surfaceHolder;
Canvas c = mHolder.lockCanvas();
mFieldDim.set(0, 0, c.getWidth(), c.getHeight());
mHolder.unlockCanvasAndPost(c);
for (int i = 0; i < mItems.size(); i++)
mItems.get(i).x = (int) (Math.random() * (float) mFieldDim.width());
mItems.get(i).y = (int) (Math.random() * (float) mFieldDim.height());
@Override
public void surfaceChanged(SurfaceHolder holder, int i, int i2, int i3)
@Override
public void surfaceDestroyed(SurfaceHolder holder)
public boolean onTouch(View v, MotionEvent event)
if (!(motionEvent.getAction() != MotionEvent.ACTION_DOWN))
PointF touch = new PointF(motionEvent.getX(), motionEvent.getY());
dugHoles.add(touch);
int radius = Math.max(mBMPHole.getHeight(), mBMPHole.getWidth()) / 2;
for (int i = mItems.size() - 1; i >= 0; i--)
Item item = mItems.get(i);
int dx = item.x - (int) touch.x;
int dy = item.y - (int) touch.y;
if (dx * dx + dy * dy < radius * radius)
mItems.remove(i);
mInventory.add(item);
Toast toast = Toast.makeText(this.getContext(), item.name + "found", Toast.LENGTH_SHORT);
toast.show();
invalidate();
return true;
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
if (mBMPField != null)
canvas.drawBitmap(mBMPField, new Rect(0, 0, mBMPField.getWidth(), mBMPField.getHeight()), mFieldDim, new Paint());
if (mBMPHole != null)
for (PointF hole : dugHoles)
canvas.drawBitmap(mBMPHole,
new Rect(0, 0, mBMPHole.getWidth(), mBMPHole.getHeight()),
new RectF(hole.x - mBMPHole.getWidth() / 2, hole.y - mBMPHole.getHeight() / 2, hole.x + mBMPHole.getWidth() / 2, hole.y + mBMPHole.getHeight() / 2),
new Paint());
private ArrayList<Item> loadItems()
InputStream input = getResources().openRawResource(R.raw.items);
BufferedReader reader = null;
ArrayList<Item> items = new ArrayList<Item>();
String itemName;
try
reader = new BufferedReader(new InputStreamReader(input));
while ((itemName = reader.readLine()) != null)
items.add(new Item(itemName));
catch (Exception e)
Log.e("MainActivity", "Reading list of items failed!", e);
finally
try
if (reader != null) reader.close();
catch (Exception e)
Log.e("MainActivity", "Error closing file reader.", e);
return items;
这是我收到的错误消息:
E/androidRuntime: 致命异常: main 进程:justinrhinehart.cse.fullsail.treasurehunter,PID:23942 java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int android.view.MotionEvent.getAction()” 在 justinrhinehart.cse.fullsail.treasurehunter.DrawSurface.onTouch(DrawSurface.java:77) 在 android.view.View.dispatchTouchEvent(View.java:14305) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118) 在 android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742) 在 com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:488) 在 com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871) 在 android.app.Activity.dispatchTouchEvent(Activity.java:4125) 在 androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 在 com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:446) 在 android.view.View.dispatchPointerEvent(View.java:14568) 在 android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6016) 在 android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5819) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310) 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367) 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333) 在 android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485) 在 android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341) 在 android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314) 在 android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367) 在 android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333) 在 android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341) 在 android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314) 在 android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8080) 在 android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8031) 在 android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7992) 在 android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8203) 在 android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220) 在 android.os.MessageQueue.nativePollOnce(本机方法) 在 android.os.MessageQueue.next(MessageQueue.java:335) 在 android.os.Looper.loop(Looper.java:183) 在 android.app.ActivityThread.main(ActivityThread.java:7656) 在 java.lang.reflect.Method.invoke(本机方法) 在 com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
谁能帮我理解问题出在哪里?
【问题讨论】:
【参考方案1】:当我认为您打算使用 onTouch()
的 event
参数时,您正在尝试使用具有未分配值的变量。你应该编辑你的 onTouch 看起来像这样:
public boolean onTouch(View v, MotionEvent event)
if (!(event.getAction() != MotionEvent.ACTION_DOWN))
PointF touch = new PointF(event.getX(), event.getY());
// ...
【讨论】:
以上是关于触摸屏时应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章