【问题标题】:singletap touch detect in Ontouch method of the view视图的 Ontouch 方法中的单点触摸检测
【发布时间】:2013-08-01 21:44:32
【问题描述】:

我需要在我的自定义视图的 ontouch 方法中进行单点触控检测。我尝试在 ACTION-DOWN 和 ACTION-UP 中获取 x 和 y 值,在 ACTION-UP 中我给出了一个条件,如果 ACTIONDOWN 和 ACTION-UP 中的 X 和 Y 值相等,则将其视为单击.

我的代码如下

@Override
public boolean onTouchEvent(MotionEvent ev) {
   if (!mSupportsZoom && !mSupportsPan) return false;

    mScaleDetector.onTouchEvent(ev);

    final int action = ev.getAction();
    switch (action & MotionEvent.ACTION_MASK) {
    case MotionEvent.ACTION_DOWN: {
        final float x = ev.getX();
        final float y = ev.getY();

        mLastTouchX = x;  //here i get x and y values in action down
        mLastTouchY = y;
        mActivePointerId = ev.getPointerId(0);

        break;
    }

    case MotionEvent.ACTION_MOVE: {
        final int pointerIndex = ev.findPointerIndex(mActivePointerId);
        final float x = ev.getX(pointerIndex);
        final float y = ev.getY(pointerIndex);

        if (mSupportsPan && !mScaleDetector.isInProgress()) {
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;

            mPosX += dx;
            mPosY += dy;
            //mFocusX = mPosX;
            //mFocusY = mPosY;

            invalidate();
        }

        mLastTouchX = x;
        mLastTouchY = y;

        break;
    }

    case MotionEvent.ACTION_UP: {

        final float x = ev.getX();
        final float y = ev.getY();

        touchupX=x;   //here is get x and y values at action up
        touchupY=y; 

        if(mLastTouchX == touchupX && mLastTouchY == touchupY){  //my condition if both the x and y values are same .

            PinchZoomPanActivity2.tapped1(this.getContext(), 100); //my method if the singletap is detected

        }
        else{

        }

        mActivePointerId = INVALID_POINTER_ID;

        break;
    }

    case MotionEvent.ACTION_CANCEL: {
        mActivePointerId = INVALID_POINTER_ID;
        break;
    }

    case MotionEvent.ACTION_POINTER_UP: {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {

            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastTouchX = ev.getX(newPointerIndex);
            mLastTouchY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
        }
        break;
    }
    }

    return true;
}

但我无法完成它。我的意思是在每次操作时都会调用我的方法。即使 actionup 和 actiondown 的 x 和 y 值不相同。而且我认为当我们用手指在屏幕上触摸时,我还需要为单击设置一些范围。谁能给我一些建议?

【问题讨论】:

  • 它永远不会在同一个地方——你的手指总是会轻微移动。使用范围检查 - 确保 abs(upLoc-downLoc)
  • 我需要使用范围检查,但我不明白你的“abs(upLoc-downLoc)
  • abs=绝对值。这意味着如果位置变化小于 5 个像素。

标签: android touch ontouchlistener


【解决方案1】:

要在 android 中检测单击和双击,我使用以下方法:

class GestureTap extends GestureDetector.SimpleOnGestureListener {
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        Log.i("onDoubleTap :", "" + e.getAction());
        return true;
   }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent e) {
        Log.i("onSingleTap :", "" + e.getAction());
        return true;
    }
}

在 GestureDetector 的构造函数中使用它:

detector = new GestureDetector(this, new GestureTap());

并在onTouch监听器中添加如下代码

@Override
public boolean onTouchEvent(MotionEvent event) {

    detector.onTouchEvent(event);

    return true;
}

【讨论】:

【解决方案2】:

为了完整起见添加答案,如果其他人到达这里:

您可以使用GestureDetectorOnTouchListener

final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
         //do something
            return true;
        }

        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) {
            return super.onDoubleTap(e);
        }
    });

 viewToTouch.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            return gestureDetector.onTouchEvent(event);
        }
    });

【讨论】:

  • 这是最简单的方法。无需重新发明轮子。
【解决方案3】:

我最近也遇到了同样的问题,最终不得不实现去抖动以使其正常工作。这并不理想,但在我找到更好的东西之前它非常可靠。

View.onClickListener 对我来说更可靠,但不幸的是我需要来自 OnTouchListener 的 MotionEvent。

编辑:删除了可能导致此处失败的多余代码

class CustomView extends View {

    private static long mDeBounce = 0;

    static OnTouchListener listenerMotionEvent = new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if ( Math.abs(mDeBounce - motionEvent.getEventTime()) < 250) {
                //Ignore if it's been less then 250ms since
                //the item was last clicked
                return true;
            }

            int intCurrentY = Math.round(motionEvent.getY());
            int intCurrentX = Math.round(motionEvent.getX());
            int intStartY = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalY(0)) : intCurrentY;
            int intStartX = motionEvent.getHistorySize() > 0 ? Math.round(motionEvent.getHistoricalX(0)) : intCurrentX;

            if ( (motionEvent.getAction() == MotionEvent.ACTION_UP) && (Math.abs(intCurrentX - intStartX) < 3) && (Math.abs(intCurrentY - intStartY) < 3) ) {
                if ( mDeBounce > motionEvent.getDownTime() ) {
                    //Still got occasional duplicates without this
                    return true;
                }

                //Handle the click

                mDeBounce = motionEvent.getEventTime();
                return true;
            }
            return false;
        }
    };
}

【讨论】:

  • 非常感谢。这很有效。根据我的说法,在 ontouch 中双击的最佳功能。多点触控时您可能会发现一些故障,但这是最好的。
  • 对我不起作用,这甚至覆盖了我的双击方法
【解决方案4】:

为视图添加GestureDetector.SimpleOnGestureListener,并在此使用方法onSingleTapConfirmed

只有当 Android 操作系统确认特定的触摸是单击而不是不是双击时,才会调用此方法。

你可以用谷歌搜索安卓的例子。

【讨论】:

  • 是的,我试过这个..但是我在使用这个单点或双点时遇到了一些其他问题。无论如何,谢谢。
  • onSingleTapConfirmed 将被调用,只有点击是单一的。这里没有混淆。看方法名本身就说看onSingleTapConfirmed。我不知道你指的是什么其他问题,我认为你没有正确处理返回值。检查一下!
  • 我的问题不在于手势监听器,而在于我的应用程序。我的应用程序包含带有多点触控平移和放大 ontouch 的自定义视图,这不适合手势监听器。
【解决方案5】:

有一种更简单直接的方法。 使用 MotionEvent.ACTION_DOWN && MotionEvent.ACTION_UP 并计时事件之间的差异。

完整的代码可以在这里找到。 https://stackoverflow.com/a/15799372/3659481

setOnTouchListener(new OnTouchListener() {
private static final int MAX_CLICK_DURATION = 200;
private long startClickTime;

@Override
public boolean onTouch(View v, MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            startClickTime = Calendar.getInstance().getTimeInMillis();
            break;
        }
        case MotionEvent.ACTION_UP: {
            long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
            if(clickDuration < MAX_CLICK_DURATION) {
                //click event has occurred
            }
        }
    }
    return true;
}

}

【讨论】:

    【解决方案6】:

    认为您不需要使用“等于”运算符。而不是使用近似值

    case MotionEvent.ACTION_DOWN: {
        final int CONST = 5;
        final float x = ev.getX();
        final float y = ev.getY();
    
        mLastTouchXMax = x+CONST;  //here i get x and y values in action down
        mLastTouchXMin = x-CONST;
        mLastTouchYMax = y+CONST;
        mLastTouchYMin = y-CONST;
        mActivePointerId = ev.getPointerId(0);
    
        break;
    }
    

    并在 ACTION_UP 中检查间隔之间的 X 和 Y 值。

    【讨论】:

    • 我不明白在行动中要做什么。我需要检查行动中的 x 和 y 值是否低于行动中的四个值。但是我将如何做到这一点。帮帮我。谢谢。
    【解决方案7】:
    float dX,dY,x,y;     
    tv.setOnTouchListener(new View.OnTouchListener() {
                                    @Override
                                    public boolean onTouch(View view, MotionEvent event) {
                                        switch (event.getAction()) {
                                            case MotionEvent.ACTION_UP:     //Event for On Click
                                                if(x==view.getX() && y==view.getY()){
                                                    Toast.makeText(getApplicationContext(),"TextView Clicked",Toast.LENGTH_LONG).show();
                                                }
                                                break;
                                            case MotionEvent.ACTION_DOWN:
                                                x=view.getX();
                                                y=view.getY();
                                                dX = view.getX() - event.getRawX();
                                                dY = view.getY() - event.getRawY();
                                                break;
    
                                            case MotionEvent.ACTION_MOVE:
                                                view.animate()
                                                        .x(event.getRawX() + dX)
                                                        .y(event.getRawY() + dY)
                                                        .setDuration(0)
                                                        .start();
                                                break;
                                            default:
                                                return false;
                                        }
                                        return true;
                                    }
                                });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多