【问题标题】:Not all touch events being received by Android view并非所有的触摸事件都被 Android 视图接收
【发布时间】:2013-01-15 07:10:58
【问题描述】:

在我的 Android 应用中,我有一个自定义的 View 来接收触摸事件。但是,我每次触摸它时它都不会做出反应 - 只是有时。据我所知,如果我触摸屏幕,移动手指,然后松开——即使我只移动一点——事件就会被拾取,但如果我点击屏幕太快以至于手指无法滑过它, 没发生什么事。我该如何解决这个问题?

这是视图的代码:

public class SpeedShooterGameView extends GameActivity.GameView {
    public SpeedShooterGameView(Context arg0, AttributeSet arg1) {
        super(arg0, arg1);
    }

    @Override
    protected GameThread getNewThread(SurfaceHolder holder, Context context) {
        return new SpeedShooterGameThread(holder, context);
    }

    // Program is driven by screen touches
    public boolean onTouchEvent(MotionEvent event) {
        SpeedShooterGameThread thread = (SpeedShooterGameThread) getThread();
        if (thread.isRunning()) {
            return thread.recieveTouch(event);
        } else {
             return false;
        }
    }
}

我非常有信心SpeedShooterGameThread thread = (SpeedShooterGameThread) getThread(); 行中返回的对象按我预期的那样工作,但如果上面的代码看起来不错,我也会发布该类中的相关代码。当thread.recieveTouch(event); 被调用时,MotionEvent 被发送到另一个线程。

编辑:我会继续发布SpeedShooterGameThread 的代码:

public class SpeedShooterGameThread extends GameActivity.GameView.GameThread {
    //... snip ...
    private Queue<MotionEvent> touchEventQueue;

    //... snip ...

    public synchronized final void newGame() { //called from the constructor, used to go to a known stable state
        //... snip ...
        touchEventQueue = new LinkedList<MotionEvent>();
        //... snip ...
    }

    //...snip...

    public synchronized boolean recieveTouch(MotionEvent event) {
        return touchEventQueue.offer(event);
    }

    private synchronized void processTouchEvents() {
        synchronized (touchEventQueue) {
            while (!touchEventQueue.isEmpty()) {
                MotionEvent event = touchEventQueue.poll();
                if (event == null) {
                    continue;
                }
                //... snip ....
            }
        }
    }

    //... snip ...
}

【问题讨论】:

  • 您确定 if 语句每次都评估为 true 吗?如果是这样,我需要查看SpeedShooterGameThread 代码以了解为什么它会返回 false。
  • 您可以在onTouchEvent 的开头放置一条日志语句以确保您收到事件,但错误很可能在thread.recieveTouch()
  • @iagreen:这是一个很好的电话。如果到那时这里没有答案,我会在我回到这个问题时尝试。
  • @Jason Robinson:我在上面发布了thread.recieveTouch() 的代码。我不认为 Queue.offer() 在我使用它时会返回 false,但我也会对此进行研究。

标签: android touch motionevent


【解决方案1】:

我通过完全删除Queue&lt;MotionEvent&gt; 修复了这个错误。我的代码现在看起来像这样:

线程不再使用Queue,当recieveTouch()被调用时MotionEvents被立即处理:

public class SpeedShooterGameThread extends GameActivity.GameView.GameThread {
//The touchEvent member has been removed.

//... snip ...

    public synchronized final void newGame() { //called from the constructor, used to go to a known stable state
        // touchEvents is no longer initialized.

        //...snip...
    }

    //...snip...

    public synchronized boolean recieveTouch(MotionEvent event) {
        //Immediately handle the MotionEvent here,
        //or return false if the event isn't processed
    }

    // The processTouchEvents() method is removed.

    //... snip ...
}

视图不变:

public class SpeedShooterGameView extends GameActivity.GameView {
    public SpeedShooterGameView(Context arg0, AttributeSet arg1) {
        super(arg0, arg1);
    }

    @Override
    protected GameThread getNewThread(SurfaceHolder holder, Context context) {
        return new SpeedShooterGameThread(holder, context);
    }

    // Program is driven by screen touches
    public boolean onTouchEvent(MotionEvent event) {
        SpeedShooterGameThread thread = (SpeedShooterGameThread) getThread();
        if (thread.isRunning()) {
            return thread.recieveTouch(event);
        } else {
             return false;
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-22
    • 1970-01-01
    • 2012-07-14
    相关资源
    最近更新 更多