首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >ScaleGestureDetector.onTouchEvent始终返回“true”

ScaleGestureDetector.onTouchEvent始终返回“true”
EN

Stack Overflow用户
提问于 2011-01-02 03:21:48
回答 3查看 6.8K关注 0票数 19

我认为"ScaleGestureDetector“实例的"onTouchEvent()”方法应该只在真正处理触摸事件时才返回"true“,即如果它检测到多点触摸缩放手势(用两个手指)。否则,我认为它应该返回"false“,以便让其他处理程序处理事件,例如,长按以触发上下文菜单。

我观察到一些不同的东西:在我的例子中,scaleGestureDetector.onTouchEvent()总是返回"true“。下面是我的MyView类的代码片段:

代码语言:javascript
复制
public boolean onTouchEvent(MotionEvent event) {
  boolean retval = scaleGestureDetector.onTouchEvent(event);
   Log.v("MyView.onTouchEvent()", "Action: " + event.getAction() +
         "; PointerCount: " + event.getPointerCount() +
         "; scaleGestureDetector.onTouchEvent() RetVal: " + retval);
   return(retval);
}

在我用一根手指触摸视图大约1秒后,产生了以下日志输出,然后用两根手指执行缩放手势:

代码语言:javascript
复制
01-01 19:09:54.484: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:54.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:54.541: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:54.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:54.820: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:54.910: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:55.050: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:55.350: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:55.400: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:09:57.160: INFO/BatteryStatsImpl(96): notePhoneSignalStrengthLocked: 4->3
01-01 19:10:00.060: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false
01-01 19:10:00.060: ERROR/ClockWidget(215): handleUiMessage~ in pause. msg:36867
01-01 19:10:00.070: ERROR/ClockWidget(215): weatherClock onReceive~ mUseAnimation:false
01-01 19:10:00.090: INFO/PI.Alarms(699): Update Alarms start
01-01 19:10:00.090: INFO/PI.Alarms(699): Task Notifications: Already displaying the same alarms, no update
01-01 19:10:00.100: INFO/PI.Alarms(699): Event Notifications: Already displaying the same alarms, no update
01-01 19:10:00.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 0; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.870: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.900: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.922: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.931: VERBOSE/MyView.onTouchEvent()(5930): Action: 261; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:00.950: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.002: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.030: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.060: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.090: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.120: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.140: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.172: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.200: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.230: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.252: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.280: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.310: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.342: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.370: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.390: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.424: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.450: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.480: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.510: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.530: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.580: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.690: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.780: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.815: VERBOSE/MyView.onTouchEvent()(5930): Action: 2; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.830: VERBOSE/MyView.onTouchEvent()(5930): Action: 262; PointerCount: 2; scaleGestureDetector.onTouchEvent() RetVal: true
01-01 19:10:01.840: VERBOSE/MyView.onTouchEvent()(5930): Action: 1; PointerCount: 1; scaleGestureDetector.onTouchEvent() RetVal: true

正如我所说的:返回值总是"true"!这是ScaleGestureDetector.onTouchEvent()的错误吗?我该怎么做才能让其他处理程序处理所有非缩放手势事件(例如,用一根手指长按)?请帮帮我!

Nemax

EN

回答 3

Stack Overflow用户

发布于 2011-01-02 04:15:27

不知道这是一个bug还是故意的,但这绝对是源代码所做的(ScaleGestureDetector.java:156):

代码语言:javascript
复制
public boolean onTouchEvent(MotionEvent event) {
   final int action = event.getAction();
   boolean handled = true;

   /* ... bunch of code that never updates 'handled' */

   return handled;
}

我解决这个问题的方法是首先检查我可能想要处理的所有其他类型的触摸事件,然后调用手势检测器。

代码语言:javascript
复制
    if (mLongPressGestureDetector != null && mLongPressGestureDetector.onTouchEvent(event))
        return true;
    else if (mIsInMoveMode && mScaleGestureDetector != null) {
        // Check for a move
        if (action == MotionEvent.ACTION_MOVE && !mScaleGestureDetector.isInProgress()) {
            handleMove(event);
            return true;
        }

        // Now a scale
        mScaleGestureDetector.onTouchEvent(event);
        return true;
    }
票数 5
EN

Stack Overflow用户

发布于 2011-03-18 08:15:26

下面是一个使用中的示例:

代码语言:javascript
复制
public boolean onTouch(View v, MotionEvent event) {

    mScaleDetector.onTouchEvent(event);

    if (!mScaleDetector.isInProgress()) {
        if (event.getAction() == MotionEvent.ACTION_DOWN || (event.getAction() == MotionEvent.ACTION_MOVE)) {
            touchX = (int) event.getX();
            touchY = (int) event.getY();
            isTouched = true;
        }

        if (event.getAction() == MotionEvent.ACTION_UP) {
            isTouched = false;
        }
    } else {
        isTouched = false;
    }

    return true;
}
票数 3
EN

Stack Overflow用户

发布于 2011-03-21 00:46:29

这就是我如何解决这个问题的:通过覆盖Acitivity的onDispatchTouchEvent()方法。任何其他的解决方案似乎都行不通。onDispatchTouchEvent()方法的好处是,它总是在将任何触摸事件转发到任何其他接收器之前被调用,因此您可以在这里拦截每个单独的触摸事件。

如果事件是在这里的某个地方处理的(缩放或滑动),我会立即返回,而不会将事件转发到超类,即视图层次结构的其余部分。如果不是,我将它转发给超类,这样其他视图就可以处理它,例如检测短点击或长点击。

但还有一些问题需要解决: 1.如果用户开始缩放手势,我必须取消任何长点击检测过程,因为接收到的视图将获得第一个向下事件,然后什么都不会发生(在第二个手指向下并开始缩放之后),然后错误地认为正在执行长按。2.当执行长按并弹出上下文菜单时,我必须在dispatchOnTouchEvent()中阻止滑动和缩放手势检测,直到下一个up事件,否则即使上下文菜单在那里,滑动和缩放也会执行。

相当复杂,但我花了很多时间和大量的试验和错误,就是找不到任何更简单的解决方案。无论如何,处理1.缩放手势,2.水平滑动手势,3.垂直滚动手势,4.长点击和5.短点击,所有这些都在相同的目标视图上,完成起来并不是一项简单的任务。

以下是代码(相关部分):

代码语言:javascript
复制
    @Override
public boolean dispatchTouchEvent(MotionEvent e) {
    if (eventInProgress) {
        // View shall only receive scale gesture event if visible
        if (targetView.isShown())
            scaleGestureDetector.onTouchEvent(e);
        if (scaleGestureDetector.isInProgress())
            motionEventConsumed = true;
    }

    if (motionEventConsumed) {
        if (e.getAction() == MotionEvent.ACTION_UP)
            motionEventConsumed = false;
        if (cancelLongPressEvent) {
            cancelLongPressEvent = false;
            targetView.cancelLongPress();
        }
        return (true);
    }

    // Get the action that was done on this touch event
    switch (e.getAction()) {
    case MotionEvent.ACTION_DOWN: {
        // store the X value when the user's finger was pressed down
        downXValue = e.getX();
        downYValue = e.getY();
        cancelLongPressEvent = true;
        eventInProgress = true;
        break;
    }

    case MotionEvent.ACTION_MOVE:
        // When having moved by too many x or y pixels, then
        // cancel any ongoing long klick events
        if (cancelLongPressEvent
                && Math.abs(e.getX() - downXValue)
                        + Math.abs(e.getY() - downYValue) > 40) {
            targetView.cancelLongPress();
            cancelLongPressEvent = false;
        }
        break;

    case MotionEvent.ACTION_UP: {
        if (eventInProgress) {
            // Get the X value when the user released his/her finger
            float deltaX = e.getX() - downXValue;
            float deltaY = e.getY() - downYValue;
            if (Math.abs(deltaX) > Math.abs(deltaY)
                    && Math.abs(deltaX) > 50) {
                // going backwards: pushing stuff to the right
                if (deltaX > 0) {
                    flipRight();
                    return (true);
                }
                // going forwards: pushing stuff to the left
                if (deltaX < 0) {
                    flipLeft();
                    return (true);
                }
                break;
            }
        }
    }
    }

    // If event was not handled here, then forward it to parent,
    // i. e. to view hierarchy
    return (super.dispatchTouchEvent(e));
}

..。

代码语言:javascript
复制
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
        ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater mi = getMenuInflater();
    mi.inflate(R.menu.lztv_context_menu, menu);
    contextMenuTargetView = v;
    eventInProgress = false;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4575355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档