Как сделать так, чтобы двойное касание и панорамирование работали одновременно на Android?

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

  • Мультитач для масштабирования
  • Touchlistener для панорамирования
  • Двойной щелчок для восстановления масштаба
  • или если он уже восстановлен, он увеличит место, где был двойной щелчок.

На данный момент все остальное работает, но когда я дважды щелкаю и удерживаю второй щелчок и продолжаю перемещать его, код работает таким образом, сначала restores/zooms, а затем panning starts.

Поэтому из-за масштабирования иногда сначала изменяется размер холста, а затем начинается панорамирование. Что я должен сделать, чтобы включить панорамирование после обнаружения двойного щелчка? Или что-то вроде проверки, продолжает ли двигаться последний щелчок двойного щелчка, и пропустить масштабирование/восстановление? Мой код выглядит как этот банкомат. И я пытаюсь вернуть false после двойного щелчка, но на самом деле это не работает ... Будет ли что-то вроде установки ignoreMultiTouch на true, но при двойном щелчке или панорамировании?

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if(mgestureDetector.onTouchEvent(ev)){
        mOnTouchEventWorkingArray[0] = ev.getX();
        mOnTouchEventWorkingArray[1] = ev.getY();

        mOnTouchEventWorkingArray = scaledPointsToScreenPoints(mOnTouchEventWorkingArray);

        ev.setLocation(mOnTouchEventWorkingArray[0], mOnTouchEventWorkingArray[1]);
        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;
                mLastTouchY = y;

                // Save the ID of this pointer
                mActivePointerId = ev.getPointerId(0);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                // Find the index of the active pointer and fetch its position
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);

                final float dx = x - mLastTouchX;
                final float dy = y - mLastTouchY;


                mPosX += dx;
                mPosY += dy;
                mTranslateMatrix.preTranslate(dx, dy);
                mTranslateMatrix.invert(mTranslateMatrixInverse);

                mLastTouchX = x;
                mLastTouchY = y;
                normal = false;

                invalidate();
                break;
            }

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

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

            case MotionEvent.ACTION_POINTER_UP: {
                // Extract the index of the pointer that left the touch sensor
                final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = ev.getX(newPointerIndex);
                    mLastTouchY = ev.getY(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;

            }
        }
    }
    return true;

}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor();
        if (detector.isInProgress()) {
            mFocusX = detector.getFocusX();
            mFocusY = detector.getFocusY();
        }
        mScaleFactor = Math.max(0.75f, Math.min(mScaleFactor, 3.0f));
        mScaleMatrix.setScale(mScaleFactor, mScaleFactor,
                mFocusX, mFocusY);
        mScaleMatrix.invert(mScaleMatrixInverse);
        invalidate();
        requestLayout();

        return true;
    }
}

private class GestureListener extends GestureDetector.SimpleOnGestureListener {

    @Override
    public boolean onDown(MotionEvent e) {
        return true;
    }

    // event when double tap occurs
    @Override
    public boolean onDoubleTap(MotionEvent e) {
        if (!normal) {
            restore();
        } else {
            zoomToSpot(e);
        }
        return false;
    }


    @Override
    public boolean onDoubleTapEvent(MotionEvent e) {
        return true;
    }
}

person niksi    schedule 13.07.2015    source источник


Ответы (1)


Итак, я заставил свой код работать с этими мелочами, сначала я добавил логическое значение с двойным щелчком

public boolean onDoubleTap(MotionEvent e) {
        if (!normal) {
            restore();
        } else {
            zoomToSpot(e);
        }
        doubleclicked = true;
        return true;
    }

затем я сделал два разных onTouchEvents и установил, что первый работает только в том случае, если двойной щелчок имеет значение false. Второй установит двойной щелчок в false, когда на экране не останется пальцев.

public boolean onTouchEvent(MotionEvent ev) {

    final int action = ev.getAction();

    if (!doubleclicked) {
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                //something...
        }
    } else {
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_UP: {
                doubleclicked = false;
                break;
            }
         }
     }
person niksi    schedule 21.07.2015