【问题标题】:ScaleGestureDetector.onTouchEvent always returns 'true'ScaleGestureDetector.onTouchEvent 始终返回“真”
【发布时间】:2011-01-01 19:21:48
【问题描述】:

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

我观察到一些不同的事情:在我的情况下,scaleGestureDetector.onTouchEvent() 总是返回“true”。我的 MyView 类的以下代码 sn-p:

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 秒钟后产生以下日志输出,然后用两根手指执行缩放手势:

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

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

Nemax

【问题讨论】:

    标签: android


    【解决方案1】:

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

    public boolean onTouchEvent(MotionEvent event) {
       final int action = event.getAction();
       boolean handled = true;
    
       /* ... bunch of code that never updates 'handled' */
    
       return handled;
    }
    

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

        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;
        }
    

    【讨论】:

    • 达人您好,谢谢您的回答。问题是我原本想让 View 的标准处理程序“View.onTouchEvent()”处理长点击,以便能够使用标准的上下文菜单管理。它会自动调用活动的“onCreateContextMenu()”方法,创建上下文菜单对话框等等。但是从我的“MyView.onTouchEvent()”方法中调用“super.onTouchEvent(event)”也总是返回“true”!!!您是否认为有可能使 a) 标准 View.onTouchEvent() 和 b) ScaleGestureDetector.onTouchEvent() 处理程序合作?问候, Nemax
    • 是的,对于可点击的视图,View.onTouchEvent 总是返回 true。您是否尝试过总是调用 super.onTouchEvent()?如果这不起作用,请按照我上面发布的示例添加您自己的长按手势检测器,然后在检测到长按时调用 performLongClick()。
    【解决方案2】:

    ScaleGestureDetector 提供了 isInProgress() 方法,它可能会做你想做的事......

    下面是它的使用示例:

    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;
    }
    

    【讨论】:

    • 你好,事实上,我最终使用了 ScaleGestureDetector 的“isInProgress()”方法。加上许多其他技巧和方法。请参阅上面我对自己问题的回答。
    【解决方案3】:

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

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

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

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

    这里是代码(相关部分):

        @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));
    }
    

    [...]

    @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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 2015-08-15
      • 2012-03-18
      相关资源
      最近更新 更多