当前位置: 首页 > 知识库问答 >
问题:

应用程序在触摸屏幕时崩溃

孙梓
2023-03-14

所以我正在制作一个简单的寻宝游戏。我已经实现了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: FATAL EXCEPTION: main Process:justinrhinehart.cse.fullsail.treasurehunter, PID: 23942android.view.ViewGroup.dispatchTouchEvent:尝试调用虚方法'intViewGroup.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)在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)在android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)在android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2742)在java.lang.NullPointerException(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. app. Activityjava: 1871)在android. java: 4125)在android. appcompat. view. WindowCallbackWrapper.调度TouchEvent(WindowCallbackWrapper. java: 69)5333)在android. view. ViewRootImpl$AsyncInputStage.转发(ViewRootImpl. java: 5485)在android. view. ViewRootImpl$InputStage. onDeliverToNext(ViewRootImpl. java: 5341)在android. view. ViewRootImpl$AsyncInputStage. Application(ViewRootImpl. java: 5542)在android. view. ViewRootImpl$InputStage.交付(ViewRootImpl. java: 5314)在android. view. ViewRootImpl$InputStage. onDeliverToNext(ViewRootImpl. java: 5367)在android. view. ViewRootImpl$InputStage. prov(ViewRootImpl: 5333)在android. view. ViewRootImpl$Input

任何人都可以帮助我了解问题所在吗?

共有1个答案

越俊艾
2023-03-14

当我认为您打算使用onTouch()事件参数时,您正在尝试使用具有未赋值的变量。您应该编辑您的onTouch以如下所示:

public boolean onTouch(View v, MotionEvent event) {
    if (!(event.getAction() != MotionEvent.ACTION_DOWN)) {
        PointF touch = new PointF(event.getX(), event.getY());
        // ...
    }
}
 类似资料:
  • 问题内容: 使用android-event-injector库,我编写了一个在触发某些事件时注入touch事件的应用程序。问题是我需要在给定的绝对坐标处注入触摸,因此我执行以下操作以获取屏幕上的位置: 这给了我屏幕上的绝对坐标。问题是触摸注入不起作用。 我可以在屏幕驱动程序中正确插入触摸,但是由于某些原因,坐标会被误解,并且触摸会注入到其他位置。以下是一些示例(我的屏幕面向横向为1024x600)

  • 是不是可以在不接触屏幕的情况下选择一个应用程序的一个按钮?我正在为残疾人开发一个应用程序,我需要控制其他应用程序而不需要触摸屏幕。我可以做一些与意图类,但并不总是解决方案。例如,你不能发送一个whatsapp,如果没有触摸屏幕的意图(你可以在框中放置文本,或者查看与特定联系人的对话,但你不能发送一个whatsapp,你需要物理选择特定按钮),所以我想知道是否有一种方法,可以选择屏幕中显示的按钮,而

  • 我的应用程序在我试图实现的闪屏后崩溃。我不知道问题发生在哪里。 我试着用两个小时来解决这个问题,甚至还研究了一下网络,但不知怎么的,我没能让它工作。也许你们可以看看代码,给我一些提示?我会很感激的。 AndroidManifest。xml launch_screen.xml activity_main.xml 风格。xml 主要活动。JAVA 所以会显示实际的启动屏幕,但之后应用程序就会崩溃。我不

  • 点击一次屏幕,就会出现一个不断扩大的圆圈效果。可以自定义圆圈颜色。Gif动画是小编不断点击屏幕产生的类似水纹的效果。 [Code4App.com]

  • 问题内容: 我们已经建立了销售点系统,现在我们需要将其实施到 触摸屏上吗?我们是否需要依次更改任何代码以使其正常工作。 而且我们正在使用键盘输入值-假设数量- 当我关注 JTextField时,是否有Java方式弹出键盘(例如android)? 问题答案: 这是有关如何实现弹出式键盘的简单示例:

  • 那么当屏幕被锁定时,是否有任何方法显示特定的XAML页面。目前我正在使用toast通知来完成此操作。但是toast通知的问题是我对UI没有太多的控制。