Сенсорный сенсорный детектор в режиме Ontouch

Мне понадобилось обнаружение touch-touch в моем настраиваемом методе ontouch. Я попытался получить значения x и y как в ACTION-DOWN, так и в ACTION-UP, и в ACTION-UP я дал условие, что если значения X и Y в ACTIONDOWN и ACTION-UP равны, то возьмите их как один крайнюй.

Мой код выглядит следующим образом

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

но я не могу это сделать. Я имею в виду, что при каждом действии вызывается мой метод. даже когда значения x и y обоих действий и действий не совпадают. и я думаю, что мне также нужно поместить некоторый диапазон в синглет, когда мы касаемся пальцем по экрану. Может ли кто-нибудь предложить мне некоторые способы?

Ответ 1

Я также столкнулся с той же проблемой в последнее время и в конечном итоге пришлось реализовать debounce, чтобы заставить его работать. Это не идеально, но он довольно надежный, пока я не смогу найти что-то лучше.

View.onClickListener был гораздо более надежным для меня, но, к сожалению, мне нужен MotionEvent от OnTouchListener.

Изменить: Удален избыточный код, который может привести к сбою здесь

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

Ответ 2

Чтобы обнаружить Single и Double Tap в 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;
}

Ответ 3

Добавление ответа для полноты и если кто-то еще достигнет здесь:

Вы можете использовать GestureDetector с OnTouchListener

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

Ответ 4

Добавить GestureDetector.SimpleOnGestureListener для представления и использования метода onSingleTapConfirmed.

Этот метод вызывается только тогда, когда ОС Android подтвердила, что касание конкретного объекта является одним нажатием, а не двойным нажатием.

Вы можете использовать Google для приложений для Android.

Ответ 5

Существует гораздо более простой и прямой путь. Используйте MotionEvent.ACTION_DOWN && MotionEvent.ACTION_UP и выберите разницу между событиями.

Полный код можно найти здесь. fooobar.com/questions/102539/...

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 между интервалами.

Ответ 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;
                                }
                            });