在SurfaceView中使用SimpleOnGestureListener的Android GestureDetector

时间:2013-03-11 14:57:31

标签: android ontouchevent gesturedetector

public class GameActivity extends Activity {
    private static final String TAG = "GameActivity";

   . . .

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "+ onTouchEvent(event:" + event + ")");
        Log.d(TAG, "- onTouchEvent()");
        return super.onTouchEvent(event);
    }

    . . .
}


public class GameView extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "GameView";

    . . .

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d(TAG, "+ onTouchEvent(event:" + event + ")");
        gestureDetector.onTouchEvent(event);
        Log.d(TAG, "- onTouchEvent()");
        return super.onTouchEvent(event);
    }

    private SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
        private static final String TAG = "GestureListener";

        @Override
        public boolean onSingleTapConfirmed(MotionEvent event) {
            Log.d(TAG, "+ onSingleTapConfirmed(event:" + event + ")");
            singleTapDetected = true;
            Log.d(TAG, "- onSingleTapConfirmed()");
            return true;
        }

        @Override
        public boolean onDoubleTap(MotionEvent event) {
            Log.d(TAG, "+ onDoubleTap(event:" + event + ")");
            doubleTapDetected = true;
            Log.d(TAG, "- onDoubleTap()");
            return true;
        }
    };

    private GestureDetector gestureDetector = new GestureDetector(getContext(), gestureListener);

    . . .
}

我在AVD上运行它,只需单击SurfaceView(GameView) 根据LogCat日志:

03-11 14:19:51.171: D/GameView(4839): + onTouchEvent(event:MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=1071.0, y[0]=437.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=27223172, downTime=27223172, deviceId=0, source=0x1002 })
03-11 14:19:51.171: D/GameView(4839): - onTouchEvent()
03-11 14:19:51.171: D/GameActivity(4839): + onTouchEvent(event:MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=1071.0, y[0]=437.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=27223172, downTime=27223172, deviceId=0, source=0x1002 })
03-11 14:19:51.171: D/GameActivity(4839): - onTouchEvent()
03-11 14:19:51.299: D/GameActivity(4839): + onTouchEvent(event:MotionEvent { action=ACTION_UP, id[0]=0, x[0]=1071.0, y[0]=437.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=27223303, downTime=27223172, deviceId=0, source=0x1002 })
03-11 14:19:51.299: D/GameActivity(4839): - onTouchEvent()

有几个问题:

  1. 为什么没有调用SimpleOnGestureListener? (即使onTouchEvent()被调用,并且可以预见行[{1}}已被执行)

  2. 为什么GameActivity的gestureDetector.onTouchEvent(event);获得 ACTION_DOWN ACTION_UP ,但GameView的onTouchEvent()只获得 ACTION_DOWN

  3. 我尝试过的一些事情

    • 我使用上面显示的相同代码在onTouchEvent()类上实现了GestureDetector,并按预期工作,调用GameActivity

    • 在GameView中,创建了一个私有onSingleTapConfirmed()而不是私有成员SimpleOnGestureListener,并用它来构建class GestureListener extends SimpleOnGestureListener。我看到了与描述相同的行为,没有调用听众。

1 个答案:

答案 0 :(得分:8)

我将代码调试到android源代码,GestureDetector类。这解释了为什么没有调用SimpleOnGestureListener

  • 收到ACTION_DOWN并为GestureDetector消息处理程序生成内部TAP消息。
  • 只有当事件仍然关闭时,处理程序才会调用监听器onSingleTapConfirmed()
  • 事件仍然失败,因为从未收到过ACTION_UP事件。

所以你看,这两个问题是相关的,当我发现为什么没有发出ACTION_UP时我会解决问题!

修改

这就完成了答案,现在它正在运作。

  • GameView中对!mStillDown的调用返回super.onTouchEvent(),因为SurfaceView的false类是View,它返回super。这就是为什么ACTION_UP永远不会被称为
  • 的原因
  • GameActivity对false的调用返回super.onTouchEvent(),这就是为什么在GameActivity上发布了ACTION_UP。

注意:如果我设置 true ,那么 GameView.setclickable(true) 会返回 super.onTouchEvent()这也是一个可接受的解决方案

现在我的GameView代码是:

true

当前的LogCat日志是:

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.d(TAG, "+ onTouchEvent(event:" + event + ")");
    gestureDetector.onTouchEvent(event);
    Log.d(TAG, "- onTouchEvent()");
    return true;
}